Maul Nav API reference

Generated from the public headers, which are the source of truth: 138 functions across 12 headers.

base.h

The base of the Maul Nav API: the library version, the export and attribute macros, the result codes every fallible function returns, the allocator and the vector types. Coordinates are meters in a right-handed frame with +Y up and -Z forward. World positions are doubles; positions within a frame the library names (a bake's origin, a tile) are binary32.

mnavVersion mnavGetVersion(void);

Returns the version of the library that was linked, which may differ from the MNAV_VERSION macros a program was compiled with.

Returns: The library version.

Thread safety. Safe from any thread.

uint64_t mnavHash64(uint64_t seed, const void* data, int64_t byteCount);

Hashes bytes into a 64-bit value, the hash every determinism check and navmesh fingerprint is built on: eight bytes a round, read in the host's byte order, xored in, multiplied by an odd constant and folded, the leftover bytes one at a time. Its constants are frozen.

Parameters:

Returns: The hash.

Thread safety. Safe from any thread.

const char* mnavGetResultName(mnavResult result);

Returns the name of a result code, for diagnostics.

Parameters:

Returns: A static, NUL-terminated string such as "mnav_errorCapacity".

Thread safety. Safe from any thread.

avoidance.h

Avoidance: local steering among agents by velocity obstacles (ORCA), apart from the navmesh: nothing here uses a navmesh, and a host may use it without one. It works on the ground plane, a 3D world's (x, z) or a 2D world's (x, y), and for fliers in space, in meters and seconds.

static inline mnavAvoidanceDef mnavDefaultAvoidanceDef(void);

Returns the default avoidance def: up to 4096 agents, each avoiding its 10 nearest neighbours within 10 m, 2 s ahead, and up to 4096 obstacle points, each agent avoiding its 16 nearest obstacle edges or circles, 2 s ahead. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateAvoidance(const mnavAvoidanceDef* def, mnavAvoidance** avoidanceOut);

Makes an avoidance set with the memory its limits need.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a def not from mnavDefaultAvoidanceDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for an allocator with one function, a limit below 1 (below 0 for obstacle vertices), a neighbor distance not more than 0 or not finite, or a horizon that is NaN or plus infinity; mnav_errorLimit for a limit past its MNAV_MAX_AVOIDANCE_ value or a horizon shorter than MNAV_MIN_AVOIDANCE_TIME; mnav_errorCapacity when the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyAvoidance(mnavAvoidance* avoidance);

Destroys an avoidance set. Called back in from the avoidance set's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the set is used by one thread at a time.

uint64_t mnavAvoidance_GetMisuse(const mnavAvoidance* avoidance);

Returns how many calls against the avoidance set were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the avoidance set was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavAvoidance_Avoid( mnavAvoidance* avoidance, const mnavAgent* agents, int32_t agentCount, const mnavObstacle* obstacles, int32_t obstacleCount, double step, mnavVec2* velocitiesOut);

Finds each agent's new velocity: the one nearest its preferred velocity, no faster than its maximum speed, that avoids the obstacles within the obstacle horizon and colliding with its neighbours within the time horizon if they do their share (ORCA); when none does, the one that keeps clear of the obstacles and breaks the agents' constraints least. An agent sees an obstacle edge only from outside it. An agent exactly on a circle's center leaves along -Y (ground -Z). An agent its neighbours or obstacles hold back from its preferred velocity aims 1% of its speed to the right of it; one held back only by its maximum speed does not. So agents meeting in perfect symmetry pass rather than stop face to face. The same agents give the same velocities in any order, on every platform.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument with agents or obstacles, a negative count, a step that is NaN or plus infinity, an agent or obstacle with a NaN value, an agent with a radius not more than 0, a maximum speed below 0 or a priority not more than 0 or not finite, a zero-length obstacle edge, a circle's radius not more than 0, another obstacle with a radius, or a polygon not counterclockwise; mnav_errorLimit for a step shorter than MNAV_MIN_AVOIDANCE_TIME, or a coordinate, speed or radius past its MNAV_MAX_AVOIDANCE_ bound, an infinity included; mnav_errorCapacity for more agents or obstacle points than the set's limits. Also mnav_errorBusy when called back in from the avoidance set's allocator, one misuse counted.

Thread safety. Safe from any thread; the set is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavAvoidance_Avoid3D( mnavAvoidance* avoidance, const mnavAgent3D* agents, int32_t agentCount, const mnavSphere* spheres, int32_t sphereCount, double step, mnavVec3* velocitiesOut);

Finds each flier's new velocity, as mnavAvoidance_Avoid does on the ground: the one nearest its preferred velocity, no faster than its maximum speed, that avoids the spheres within the obstacle horizon and colliding with its neighbours within the time horizon if they do their share (ORCA in space); when none does, the one that keeps clear of the spheres and breaks the agents' constraints least. An agent its neighbours or spheres hold back from its preferred velocity aims 1% of its speed to the right of it, +Y being up; rising vertically it turns toward +X, falling toward -X. One held back only by its maximum speed does not. A flier exactly on a sphere's center leaves along -Z. The same agents give the same velocities in any order, on every platform.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument with agents or spheres, a negative count, a step that is NaN or plus infinity, an agent or sphere with a NaN value or a radius not more than 0, or an agent with a maximum speed below 0 or a priority not more than 0 or not finite; mnav_errorLimit for a step shorter than MNAV_MIN_AVOIDANCE_TIME, or a coordinate, speed or radius past its MNAV_MAX_AVOIDANCE_ bound, an infinity included; mnav_errorCapacity for more agents than the set's limit or more spheres than its obstacle points. Also mnav_errorBusy when called back in from the avoidance set's allocator, one misuse counted.

Thread safety. Safe from any thread; the set is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavAvoidance_Debug(mnavAvoidance* avoidance, const mnavAgent* agents, int32_t agentCount, double height, mnavDebugBuffer* buffer);

Appends each agent's outline, a 16-gon (mnav_debugAgent), and a line to each neighbour mnavAvoidance_Avoid would give it (mnav_debugNeighbor), at a height, agent X and Y lying at ground X and Z.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument with agents, a height not finite, or a buffer with a count out of range, an array missing or an origin not finite; for an agent mnavAvoidance_Avoid refuses, the status it gives; mnav_errorCapacity for more agents than the set's limit, or when the buffer filled, its counts saying what the whole needs. Also mnav_errorBusy when called back in from the avoidance set's allocator, one misuse counted.

Thread safety. Safe from any thread; the set and the buffer are used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavAvoidance_Debug3D(mnavAvoidance* avoidance, const mnavAgent3D* agents, int32_t agentCount, const mnavSphere* spheres, int32_t sphereCount, mnavDebugBuffer* buffer);

Appends each flier's outline, three 16-gons on its radius, one in each axis plane (mnav_debugAgent), a line to each neighbour mnavAvoidance_Avoid3D would give it (mnav_debugNeighbor), and each sphere's three rings (mnav_debugObstacle).

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument with agents or spheres, a negative count, or a buffer with a count out of range, an array missing or an origin not finite; for an agent or sphere mnavAvoidance_Avoid3D refuses, or more of them than it takes, the status it gives; mnav_errorCapacity when the buffer filled, its counts saying what the whole needs. Also mnav_errorBusy when called back in from the avoidance set's allocator, one misuse counted.

Thread safety. Safe from any thread; the set and the buffer are used by one thread at a time.

bake.h

The bake's settings and its input surface: the def a bake runs with, the agent profile it bakes for, the named limits that bound its work, and the triangle meshes a host hands it, each checked before any work.

static inline mnavBakeDef mnavDefaultBakeDef(void);

Returns the default bake def: cells of 0.25 m by 0.125 m, tiles of 128 cells, an agent 0.5 m in radius and 2 m tall that steps 0.75 m and walks slopes up to 45 degrees, regions of at least 2 square meters, walls within 0.3 m of the cells and at most 12 m long, detail samples every 1.5 m within 0.125 m, and limits sized for a large level. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def, with a valid cookie.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavBakeDefResult mnavValidateBakeDef(const mnavBakeDef* def, mnavBakeCells* cellsOut);

Checks a bake def and converts its meters to cells.

Parameters:

Returns: mnav_success; mnav_errorInvalid with the setting for a NULL def, a def without its cookie, an allocator with one function, a NaN, a value (an infinity included) outside the range its field gives with no named constant, or an agent radius whose border is wider than a tile; mnav_errorLimit with the setting for a value past an MNAV_MIN_ or MNAV_MAX_ bound its field names, an infinity and an agent height or step height past MNAV_MAX_HEIGHT_CELLS included; mnav_errorVersion with no setting for a def built against another version of the headers.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavInputResult mnavValidateBakeInput(const mnavBakeDef* def, const mnavBakeInput* input);

Checks a 3D bake's whole input as hostile input to a bake with a def, as mnavBaker_BakeTile checks it, without baking: every mesh, all of its triangles even with a tile index, every terrain and volume, their size against the def's inputTriangles limit, and that the tile index fits them, for an import step that wants to catch bad input early. Input it accepts, every bake with the def accepts at its input stage; a bake may still refuse later, for a tile past the extent, a piece past MNAV_MAX_PIECE_CORNERS or a limit reached, as mnavBaker_BakeTile's return value says.

Parameters:

Returns: mnav_success; for a def mnavValidateBakeDef refuses, the status it gives; mnav_errorInvalid for a NULL argument, a negative count or a NULL array with a positive count, or a tile index that mnavBaker_BakeTile refuses; for a mesh, a terrain or a volume, the status mnavBaker_BakeTile gives it, the input and its element named; mnav_errorCapacity for more input triangles in all than the inputTriangles limit, a terrain's triangles and a volume's points counted.

Thread safety. Safe from any thread. A tile index may be read by any number of checks and bakes at once.

MNAV_NODISCARD MNAV_API mnavInputResult mnavValidateBake2DInput(const mnavBakeDef* def, const mnavBake2DInput* input);

Checks a 2D bake's whole input as hostile input to a bake with a def, as mnavBaker_BakeTile2D checks it, without baking: every outline, their points against the def's inputTriangles limit, and that the tile index fits them. Input it accepts, every 2D bake with the def accepts at its input stage; a bake may still refuse later, as mnavBaker_BakeTile2D's return value says.

Parameters:

Returns: mnav_success; for a def mnavValidateBakeDef refuses, the status it gives; mnav_errorInvalid for a NULL argument, a negative count or NULL outlines with a positive count, or a tile index that mnavBaker_BakeTile2D refuses; for an outline, the status mnavBaker_BakeTile2D gives it, the outline and its point named: mnav_errorInvalid for fewer than 3 points, an area of MNAV_AREA_TYPES or more, or a point with a NaN coordinate, mnav_errorLimit for a point past the extent input may have, an infinity included; mnav_errorCapacity for more points in all than the inputTriangles limit.

Thread safety. Safe from any thread. A tile index may be read by any number of checks and bakes at once.

MNAV_NODISCARD MNAV_API mnavBakeDefResult mnavCreateBaker(const mnavBakeDef* def, mnavBaker** bakerOut);

Makes a baker from a def: checks the def and keeps a copy, its allocator and its memory limit.

Parameters:

Returns: mnav_success; for a def mnavValidateBakeDef refuses, the status and setting it gives; mnav_errorInvalid for a NULL bakerOut; mnav_errorCapacity when the baker does not fit the def's memory limit or the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyBaker(mnavBaker* baker);

Destroys a baker and the tile it holds. Called back in from host code a call on the baker runs (an allocator, the clock), it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the baker is used by one thread at a time.

uint64_t mnavBaker_GetMisuse(const mnavBaker* baker);

Returns how many calls against the baker were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the baker was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavBaker_BakeTile(mnavBaker* baker, const mnavBakeInput* input, int32_t tileX, int32_t tileZ, mnavBakeReport* reportOut);

Bakes tile (tileX, tileZ) of triangle meshes and terrains, shaped by volumes: checks the input, then rasterizes, filters, partitions, traces and triangulates the tile and lays its detail, and keeps the tile's bytes for mnavBaker_CopyTile, in place of any tile baked before. The same input and def give the same bytes on every platform. A terrain's triangles count as input triangles, after the meshes', toward the limits and the fingerprint, and a volume's points count as input triangles too. The report names a refused mesh, terrain or volume by its kind and its index in that kind's array. Given a tile index, the bake checks each mesh's counts and pointers and then only the triangles the index lists for the tile, with their vertices, before reading them.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL baker or input, a negative count, NULL meshes, terrains or volumes with a positive count, or a mesh mnavValidateBakeInput refuses (the report names it); a terrain with fewer than 2 samples on a side, a spacing not more than 0 or not finite, a NaN height (the sample) or an area of MNAV_AREA_TYPES or more (the cell) is mnav_errorInvalid, a side past MNAV_MAX_TERRAIN_SIDE or a sample past the extent input may have mnav_errorLimit; a volume with fewer than 3 points, a negative kind or one past mnav_volumeArea, an area volume's area not walkable, heights not finite or backward, or a NaN point coordinate (the point) is mnav_errorInvalid, a point past the extent, an infinity included (the point), mnav_errorLimit; a tile index made for another grid, another number of meshes or another number of triangles in a mesh is mnav_errorInvalid; mnav_errorLimit for a mesh past the extent, a tile past it, or a triangle that rasterizing cuts into a piece of more than MNAV_MAX_PIECE_CORNERS corners, which only rounding can cause (the report's stage says where); mnav_errorCapacity when a named limit or the memory limit is reached or the allocator fails. On failure the baker holds no tile. Also mnav_errorBusy when called back in from host code a call on the baker runs (an allocator, the clock), one misuse counted.

Thread safety. Safe from any thread; the baker is used by one thread at a time. Bakers share nothing, so one per thread bakes tiles in parallel.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateTileIndex(const mnavBakeDef* def, const mnavTriangleMesh* meshes, int32_t meshCount, mnavTileIndex** indexOut, mnavBakeReport* reportOut);

Makes a tile index of meshes for a def's tile grid: checks every mesh as a bake does, then lists for each tile the triangles whose ground bounds, widened by the tile's border and two cells, reach it, in input order. A bake given the index through mnavBakeInput reads only the tile's list and makes the same tile, to the byte, as a bake that reads every triangle. Changing a mesh's vertices or triangles calls for a new index.

Parameters:

Returns: mnav_success; for a def mnavValidateBakeDef refuses, the status it gives; for a mesh mnavValidateBakeInput refuses, the status it gives; mnav_errorInvalid for a NULL indexOut, a negative count or NULL meshes with a positive count; mnav_errorLimit past MNAV_MAX_INDEX_ENTRIES listed triangles or tiles of the grid; mnav_errorCapacity past the def's memory limit or when the allocator fails.

Thread safety. Safe from any thread. An index is never changed after it is made, so any number of bakes on any threads may read it at once.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateTileIndex2D(const mnavBakeDef* def, const mnavOutline* outlines, int32_t outlineCount, mnavTileIndex** indexOut, mnavBakeReport* reportOut);

Makes a tile index of 2D outlines for a def's tile grid, as mnavCreateTileIndex does of meshes: checks every outline as a 2D bake does, then lists for each tile the outlines whose bounds, widened by the tile's border and two cells, reach it, in input order. A bake given the index through mnavBake2DInput reads only the tile's list and makes the same tile, to the byte.

Parameters:

Returns: As mnavCreateTileIndex, for outlines.

Thread safety. Safe from any thread. An index is never changed after it is made, so any number of bakes on any threads may read it at once.

void mnavDestroyTileIndex(mnavTileIndex* index);

Destroys a tile index. Called back in from the index's allocator, or from host code a bake reading the index runs, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the index is used by one thread at a time. No bake may be reading it.

uint64_t mnavTileIndex_GetMisuse(const mnavTileIndex* index);

Returns how many calls against the tile index were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the tile index was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavBaker_BakeTile2D(mnavBaker* baker, const mnavBake2DInput* input, int32_t tileX, int32_t tileZ, mnavBakeReport* reportOut);

Bakes tile (tileX, tileZ) of 2D outlines: checks the outlines, fills the cells whose centers a walkable outline holds and no obstruction does as a flat floor at height 0, with the highest area among the outlines holding them, then erodes, partitions, traces and triangulates as mnavBaker_BakeTile does; the walkable filters, which judge heights, do not run. The report names a refused outline, and its triangles count the outlines reaching the tile. Given a tile index of the outlines, the bake checks only the outlines it lists for the tile, which hold every outline reaching it, and makes the same tile to the byte; the total of the points still counts every outline.

Parameters:

Returns: As mnavBaker_BakeTile, for outlines: a NULL input is mnav_errorInvalid, and so is a tile index made for another grid, for meshes, or for another number of outlines or of points in one; also mnav_errorCapacity for more points in all than the inputTriangles limit, or more outlines reaching the tile than the tileTriangles limit. Also mnav_errorBusy when called back in from host code a call on the baker runs (an allocator, the clock), one misuse counted.

Thread safety. Safe from any thread; the baker is used by one thread at a time. Bakers share nothing, so one per thread bakes tiles in parallel.

MNAV_NODISCARD MNAV_API mnavResult mnavBaker_CopyTile(const mnavBaker* baker, uint8_t* bufferOut, size_t capacity, size_t* sizeOut);

Copies the last baked tile's bytes into caller memory.

Parameters:

Returns: mnav_success; mnav_errorCapacity when the buffer is smaller than the tile, with the size still written; mnav_errorInvalid for a NULL baker or a NULL buffer with a positive capacity; mnav_errorState for a baker holding no tile, before its first bake or after a failed one.

Thread safety. Safe from any thread; the baker is used by one thread at a time.

static inline mnavTileCacheDef mnavDefaultTileCacheDef(void);

Returns the default tile cache def: up to 4096 tiles in 64 MiB. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateTileCache(const mnavTileCacheDef* def, mnavTileCache** cacheOut);

Makes an empty tile cache.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a def not from mnavDefaultTileCacheDef, an allocator with one function or a limit below 1; mnav_errorVersion for one built against another version of the headers; mnav_errorLimit for more tiles than MNAV_MAX_CACHED_TILES; mnav_errorCapacity when the cache does not fit its memory or the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyTileCache(mnavTileCache* cache);

Destroys a tile cache and everything it holds. Called back in from host code a call on the cache runs (an allocator, the clock), it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the cache is used by one thread at a time.

uint64_t mnavTileCache_GetMisuse(const mnavTileCache* cache);

Returns how many calls against the tile cache were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the tile cache was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavBaker_BakeTileCached(mnavBaker* baker, mnavTileCache* cache, const mnavBakeInput* input, int32_t tileX, int32_t tileZ, mnavBakeReport* reportOut);

Bakes a tile as mnavBaker_BakeTile does and keeps what a rebuild needs in the cache, replacing what it held for the tile.

Parameters:

Returns: As mnavBaker_BakeTile; mnav_errorInvalid for a NULL cache; mnav_errorCapacity when the cache holds its most tiles or bytes, with no tile baked and the tile's old entry dropped. Also mnav_errorBusy when called back in from host code a call on the baker or the cache runs (an allocator, the clock), one misuse counted.

Thread safety. Safe from any thread; the baker and the cache are used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavBaker_RebuildTile(mnavBaker* baker, mnavTileCache* cache, int32_t tileX, int32_t tileZ, const mnavBakeVolume* obstacles, int32_t obstacleCount, mnavBakeReport* reportOut);

Rebuilds a cached tile with obstacles, without its triangles: the cached field, the cached volumes and then the obstacles, run from the volumes on. The bytes are those mnavBaker_BakeTile gives the same input with the obstacles appended to its volumes. An exclude obstacle carves, an area obstacle changes the area within it.

Parameters:

Returns: mnav_success; mnav_errorNotLoaded for a tile the cache does not hold; mnav_errorInvalid for a NULL argument, a negative count or a baker of another def; for an obstacle a bake refuses as a volume, the status the bake gives, the obstacle named in the report; otherwise as mnavBaker_BakeTile. Also mnav_errorBusy when called back in from host code a call on the baker or the cache runs (an allocator, the clock), one misuse counted.

Thread safety. Safe from any thread; the baker and the cache are used by one thread at a time.

void mnavTileCache_DropTile(mnavTileCache* cache, int32_t tileX, int32_t tileZ);

Drops what the cache holds for a tile, if anything. Called back in from host code a call on the cache runs (an allocator, the clock), it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the cache is used by one thread at a time.

uint64_t mnavTileCache_GetBytes(const mnavTileCache* cache);

Returns the bytes a tile cache holds, its tiles' and its own.

Parameters:

Returns: The bytes; 0 for NULL.

Thread safety. Safe from any thread; the cache is used by one thread at a time.

debug.h

Debug geometry of navmeshes, links, paths and corridors, as plain vertex and index data in a caller's buffer.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_Debug(const mnavNavmesh* navmesh, const mnavTileRange* tiles, mnavDebugBuffer* buffer);

Appends the committed tiles on a box of places: each polygon's detail triangles (mnav_debugPolygon, its area), its edges as lines (inner edges once, walls, tile sides) and each tile's bounds on the ground at its lowest detail height.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a range backward, or a buffer with a count out of range, an array missing or an origin not finite; mnav_errorCapacity when the buffer filled, its counts saying what the whole needs.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the buffer is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_DebugLinks(const mnavNavmesh* navmesh, mnavDebugBuffer* buffer);

Appends every committed off-mesh link as an arc of eight lines from its start to its end, rising a quarter of its length: at its snapped points when attached, its defined ones otherwise.

Parameters:

Returns: As mnavNavmesh_Debug.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the buffer is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavDebugPath(const mnavPath* path, mnavDebugBuffer* buffer);

Appends a path's straight line, point to point. The path may be the caller's own: its points are the caller's memory, read only from points for pointCount points, each checked, and nothing else of it is read.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a path with a negative count, no points or a point that is not finite, or a buffer as mnavNavmesh_Debug refuses it; mnav_errorCapacity when the buffer filled.

Thread safety. Safe from any thread; the buffer is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_DebugCorridor(const mnavNavmesh* navmesh, const mnavPolygonId* polygons, int32_t count, mnavDebugBuffer* buffer);

Appends the detail triangles of a run of polygons, a path's or a corridor's, each tagged with its place in the run; polygons whose tile has gone are skipped.

Parameters:

Returns: As mnavNavmesh_Debug, and mnav_errorInvalid for a polygon id never handed out.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the buffer is used by one thread at a time.

flight.h

Flight volumes: where agents that fly or swim may go, baked per tile from the navmesh bake's input into a compact sparse voxel octree, loaded from bytes, staged and committed together as navmesh tiles are.

static inline mnavFlightDef mnavDefaultFlightDef(void);

Makes a flight def with every setting at its default: 1 m voxels, tiles of 32 voxels, a volume from 0 to 64 m, a flier of 0.5 m, the ground below solid, and limits for a medium world. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

static inline mnavFlightVolumeDef mnavDefaultFlightVolumeDef(void);

Returns the default flight volume def: tiles of the default flight def, up to 65536 of them in 256 MiB. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def, with a valid cookie.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavFlightDefResult mnavValidateFlightDef(const mnavFlightDef* def);

Checks a flight def.

Parameters:

Returns: mnav_success; mnav_errorInvalid with the setting for a NULL def, a def without its cookie, an allocator with one function, a NaN, a value (an infinity included) outside the range its field gives with no named constant, or not a power of two where one is needed; mnav_errorLimit with the setting for a value past an MNAV_MIN_ or MNAV_MAX_ bound its field names, an infinity included; mnav_errorVersion with no setting for a def built against another version of the headers.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavFlightDefResult mnavCreateFlightBaker(const mnavFlightDef* def, mnavFlightBaker** bakerOut);

Makes a flight baker: checks a def and keeps a copy, its allocator and its memory limit.

Parameters:

Returns: mnav_success; for a def mnavValidateFlightDef refuses, the status and setting it gives; mnav_errorInvalid for a NULL bakerOut; mnav_errorCapacity when the baker does not fit the def's memory limit or the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyFlightBaker(mnavFlightBaker* baker);

Destroys a flight baker and the tile it holds. Called back in from the flight baker's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the baker is used by one thread at a time.

uint64_t mnavFlightBaker_GetMisuse(const mnavFlightBaker* baker);

Returns how many calls against the flight baker were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the flight baker was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightBaker_BakeTile(mnavFlightBaker* baker, const mnavBakeInput* input, int32_t tileX, int32_t tileZ, mnavFlightBakeReport* reportOut);

Bakes one flight tile from the input a navmesh bake reads: every triangle is rasterized at the voxel size, and a voxel any triangle touches is solid; with enableGroundFill, so is each column below its lowest solid voxel; then every voxel within the flier's radius of a solid one, by whole voxels, is blocked too. A tile index in the input is not used: it lists triangles for a navmesh's tiles. The tile's bytes are the same on every platform.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL baker or input; for input mnavBaker_BakeTile refuses, the status it gives, the input named in the report; mnav_errorLimit for a tile past the extent, or when rasterizing cuts a triangle into a piece of more than MNAV_MAX_PIECE_CORNERS corners, as for mnavBaker_BakeTile; mnav_errorCapacity past a named limit or the memory limit, or when the allocator fails. Also mnav_errorBusy when called back in from the flight baker's allocator, one misuse counted.

Thread safety. Safe from any thread; the baker is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightBaker_CopyTile(const mnavFlightBaker* baker, uint8_t* bufferOut, size_t capacity, size_t* sizeOut);

Copies the last baked flight tile's bytes into caller memory.

Parameters:

Returns: mnav_success; mnav_errorCapacity when the buffer is smaller than the tile, with the size still written; mnav_errorInvalid for a NULL baker or a NULL buffer with a positive capacity; mnav_errorState for a baker holding no tile, before its first bake or after a failed one.

Thread safety. Safe from any thread; the baker is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavFlightVolumeDefResult mnavCreateFlightVolume(const mnavFlightVolumeDef* def, mnavFlightVolume** volumeOut);

Makes an empty flight volume from a def: checks the def and keeps a copy, its allocator and its limits.

Parameters:

Returns: mnav_success; mnav_errorInvalid with the setting for a NULL def, a def without its cookie, an allocator with one function or a limit below 1; mnav_errorLimit with the setting for more tiles than MNAV_MAX_TILES; mnav_errorVersion with no setting for a def built against another version of the headers; for a flight def mnavValidateFlightDef refuses, the status it gives with mnav_flightVolumeSettingFlight and its setting; mnav_errorInvalid for a NULL volumeOut; mnav_errorCapacity when the volume does not fit the def's memory limit or the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyFlightVolume(mnavFlightVolume* volume);

Destroys a flight volume, its tiles and everything staged. Called back in from the flight volume's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the volume is used by one thread at a time.

uint64_t mnavFlightVolume_GetMisuse(const mnavFlightVolume* volume);

Returns how many calls against the flight volume were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the flight volume was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavTileResult mnavFlightVolume_StageTile(mnavFlightVolume* volume, const uint8_t* bytes, size_t size);

Loads flight tile bytes, checking every field as hostile input and the tile's settings against the volume's def, and stages the tile for the next commit, in place of anything staged at its place before. Queries do not see it until the commit.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument; mnav_errorFormat naming the section and element for malformed bytes, a tile baked with other settings, past the def's node or leaf limit or at a place past the extent the bake writes (the header); mnav_errorVersion for another flight tile format version; mnav_errorCapacity past the memory limit or when the allocator fails. Also mnav_errorBusy when called back in from the flight volume's allocator, one misuse counted.

Thread safety. Safe from any thread; the volume is used by one thread at a time. Staging changes nothing queries read, but it may not run beside another call that stages or commits.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_StageTileRemoval(mnavFlightVolume* volume, int32_t tileX, int32_t tileZ);

Stages the removal of the flight tile at a place for the next commit, in place of anything staged there before.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL volume; mnav_errorCapacity past the memory limit or when the allocator fails. Also mnav_errorBusy when called back in from the flight volume's allocator, one misuse counted.

Thread safety. Safe from any thread; the volume is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_Commit(mnavFlightVolume* volume);

Applies everything staged at once: installs and removes the tiles. Either all of it applies or, on failure, nothing does and the staged changes stay.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL volume; mnav_errorCapacity when the tiles would pass the tiles limit or memory its limit, or when the allocator fails. Also mnav_errorBusy when called back in from the flight volume's allocator, one misuse counted.

Thread safety. Safe from any thread; the volume is used by one thread at a time, so no query may run during a commit.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_GetTile(const mnavFlightVolume* volume, int32_t tileX, int32_t tileZ, uint64_t* fingerprintOut);

Reads the fingerprint of the flight tile committed at a place, as its bake reported it, so that a host can tell whether its input has changed since.

Parameters:

Returns: mnav_success; mnav_errorNotLoaded when no tile is committed there; mnav_errorInvalid for a NULL argument.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_IsOpen(const mnavFlightVolume* volume, mnavPos3 point, bool* openOut);

Tells whether the flier's center may be at a point: whether the voxel holding it is neither solid nor within the flier's radius of a solid voxel.

Parameters:

Returns: mnav_success; mnav_errorNotLoaded when no tile is committed under the point; mnav_errorInvalid for a NULL argument or a point with a NaN coordinate; mnav_errorOutside for a point below or above the volume, openOut false; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindFlightPath(mnavQuery* query, const mnavFlightVolume* volume, mnavPos3 start, mnavPos3 end, mnavFlightPath* pathOut);

Finds a flier's path between two points: Lazy Theta* (Nash, Koenig and Tovey, 2010) over the open blocks of the committed tiles, linked through shared faces, each block entered at the point of its face nearest the point the path comes from. A point is in sight of another when the segment between them crosses no blocked voxel, nor an edge or corner of one. The search keeps to the query context's node budget and path length limit; short of the end, the path runs to the point searched nearest it.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a point with a NaN coordinate; mnav_errorOutside for a point below or above the volume; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time, and the volume is not changed during the search.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_BeginFlightPath(mnavQuery* query, const mnavFlightVolume* volume, mnavPos3 start, mnavPos3 end);

Begins a flier's path search to run in slices: the same search as mnavQuery_FindFlightPath, continued by mnavQuery_ContinueFlightPath and ended by mnavQuery_FinishFlightPath. Whatever the slices, the path is the one mnavQuery_FindFlightPath gives. It looks over the end's space for a closed one, up to 512 blocks, before the first slice.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a point with a NaN coordinate; mnav_errorOutside for a point below or above the volume, the context's search left as it was; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_ContinueFlightPath(mnavQuery* query, const mnavFlightVolume* volume, int32_t nodes, bool* endedOut);

Continues a search begun by mnavQuery_BeginFlightPath: closes up to a number of nodes, fewer when the search ends first.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, fewer than 1 node, or a volume other than the search's; mnav_errorState for no flight search begun, or a volume committed to since the search began: begin again. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time, and the volume is not changed during the call.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FinishFlightPath(mnavQuery* query, const mnavFlightVolume* volume, mnavFlightPath* pathOut);

Ends a search begun by mnavQuery_BeginFlightPath and writes its path: as mnavQuery_FindFlightPath's when it has ended; otherwise to the point searched nearest the end, its end mnav_pathUnfinished.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a volume other than the search's; mnav_errorState for no flight search begun, or a volume committed to since the search began. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time, and the volume is not changed during the call.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_Raycast(const mnavFlightVolume* volume, mnavPos3 from, mnavPos3 to, mnavFlightHit* hitOut);

Casts a flier's ray: walks the voxels the segment crosses, and where it passes an edge or a corner every voxel it touches, and stops at the first one the flier may not enter or with no tile.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a point with a NaN coordinate; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_CheckPath(const mnavFlightVolume* volume, const mnavPos3* points, int32_t pointCount, int32_t* stepOut, mnavFlightHit* hitOut);

Checks a flier's path against the volume as it is now: casts each step's ray in order, as mnavFlightVolume_Raycast does, and stops at the first step that meets a voxel the flier may not enter or a place with no tile. A host that follows a path checks what is left of it after a commit, and searches again from where it is when a step fails.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a negative count or a point with a NaN coordinate; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included; either before any step is cast.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_FindNearestPoint(const mnavFlightVolume* volume, mnavPos3 point, float radius, mnavPos3* nearestOut, bool* foundOut);

Finds the nearest point open to the flier's center within a radius of a point: the point itself when it is open, or else a point just inside the nearest open voxel, at most a thousandth of a voxel in from its face. Tiles not loaded are not searched.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a point with a NaN coordinate, or a radius below 0 or not finite; mnav_errorLimit for a point more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavFlightVolume_Debug(const mnavFlightVolume* volume, mnavPos3 low, mnavPos3 high, mnavDebugBuffer* buffer);

Appends the open blocks of a flight volume's octrees inside a box, each as a wire box of twelve lines (mnav_debugFlightBlock, its value the block's side in voxels), drawn once however much of it the box holds; solid space shows as the gaps. A block shows where a flier's center may go and how the octree merged open space.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a corner with a NaN coordinate, a box backward, or a buffer with a count out of range, an array missing or an origin not finite; mnav_errorLimit for a corner more than MNAV_MAX_FLIGHT_VOXELS voxels from the origin, an infinity included or a box of more than MNAV_MAX_FLIGHT_DEBUG_VOXELS voxels within the floor and ceiling; mnav_errorCapacity when the buffer filled, its counts saying what the whole needs.

Thread safety. Safe from any thread. Any number of threads may read the volume at once between commits; the buffer is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavDebugFlightPath(const mnavFlightPath* path, mnavDebugBuffer* buffer);

Appends a flight path's steps, point to point (mnav_debugPath). The path may be the caller's own: its points are the caller's memory, read only from points for pointCount points, each checked, and nothing else of it is read.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a path with a negative count, no points or a point that is not finite, or a buffer as mnavFlightVolume_Debug refuses it; mnav_errorCapacity when the buffer filled.

Thread safety. Safe from any thread; the buffer is used by one thread at a time.

flow.h

Flow fields: for every cell of a grid, the cost of its cheapest way to the nearest of a set of goals and the next cell on it, so that any number of agents sharing the goals find their way at the cost of one search.

static inline mnavGridFlowDef mnavDefaultGridFlowDef(void);

Returns the default grid flow field def: up to 65536 cells. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateGridFlow(const mnavGridFlowDef* def, mnavGridFlow** fieldOut);

Makes a grid flow field with the memory its cell limit needs.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a def not from mnavDefaultGridFlowDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for an allocator with one function or a cell limit below 1; mnav_errorLimit for a cell limit past MNAV_MAX_GRID_FLOW_CELLS; mnav_errorCapacity when the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyGridFlow(mnavGridFlow* field);

Destroys a grid flow field. Called back in from the field's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the field is used by one thread at a time.

uint64_t mnavGridFlow_GetMisuse(const mnavGridFlow* field);

Returns how many calls against the grid flow field were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the grid flow field was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_Begin(mnavGridFlow* field, const mnavGrid* grid, const mnavCellRange* region, const mnavCell* goals, int32_t goalCount, const mnavQueryFilter* filter);

Begins building the field for a region of a grid and a set of goal cells: one search from all the goals, with the steps of mnavQuery_FindGridPath, to the 8 neighbours, never across a blocked corner, a step costing its length times the mean of its two cells' area costs. Cells outside the region are as blocked. A cell's way to the goals is a cheapest one, ties going to the neighbour found first by cost, then by index; the same grid, region and goals give the same field on every platform, however the work is divided. Blocked goals and goals outside the region are left out. mnavGridFlow_Continue does the work.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a negative count, a grid with no areas, a side below 1 or a cell size not more than 0 or not finite, a region backward or not within the grid, a goal outside the grid, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a side past MNAV_MAX_GRID_SIDE or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorCapacity for a region of more cells than the field's limit. On an error the field holds nothing. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_Continue(mnavGridFlow* field, const mnavGrid* grid, int32_t cells, bool* endedOut);

Continues the work begun on a field: settles up to a number of cells, fewer when the work ends first.

Parameters:

Returns: mnav_success, also when the work had already ended; mnav_errorInvalid for a NULL field or grid, fewer than 1 cell, or a grid of another size or cell size; mnav_errorState for no work begun. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_Update(mnavGridFlow* field, const mnavGrid* grid, const mnavCell* goals, int32_t goalCount, const mnavCell* changed, int32_t changedCount);

Begins repairing the field after its goals or the areas of some of its grid's cells changed: only the cells whose ways change are searched again, and when the work ends the field is the one mnavGridFlow_Begin would make with the new goals and areas, bit for bit. The cells whose ways ran through what changed are reset in this call; mnavGridFlow_Continue does the rest by its budget.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument with a count, a negative count, a grid of another size or cell size or with no areas, or a goal or changed cell outside the grid; mnav_errorState for nothing begun, or while work on the field has not ended. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_Build(mnavGridFlow* field, const mnavGrid* grid, const mnavCell* goals, int32_t goalCount, const mnavQueryFilter* filter);

Builds the field for a whole grid and a set of goal cells: begins as mnavGridFlow_Begin and continues to the end.

Parameters:

Returns: As mnavGridFlow_Begin. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_GetFlow(const mnavGridFlow* field, mnavCell cell, mnavCellFlow* flowOut);

Reads a cell's way to the goals from the field.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument; mnav_errorOutside for a cell outside the field's region; mnav_errorState for nothing begun, or while work begun on the field has not ended.

Thread safety. Safe from any thread. Any number of threads may read a field at once while no work runs on it.

MNAV_NODISCARD MNAV_API mnavResult mnavGridFlow_Debug(const mnavGridFlow* field, double height, mnavDebugBuffer* buffer);

Appends an arrow for each cell of the field that has a next cell (mnav_debugFlow): from the cell's center toward the next one's, 0.8 of a cell long, with two barbs, at a height, grid cell (x, y) lying at ground X and Z by the grid's cell size.

Parameters:

Returns: mnav_success, appending nothing when nothing was begun; mnav_errorInvalid for a NULL argument, a height not finite, or a buffer with a count out of range, an array missing or an origin not finite; mnav_errorState while work begun on the field has not ended; mnav_errorCapacity when the buffer filled, its counts saying what the whole needs.

Thread safety. Safe from any thread. Any number of threads may read a field at once while no work runs on it; the buffer is used by one thread at a time.

hierarchy.h

Hierarchical paths: an abstract graph over clusters of tiles, whose transitions stand at the portals between clusters, for long paths on large navmeshes; a path found on it is refined by the navmesh search confined to the clusters it crosses.

static inline mnavHierarchyDef mnavDefaultHierarchyDef(void);

Returns the default hierarchy def: clusters of 4 by 4 tiles, up to 4,096 tile slots, 16,384 transitions and 262,144 edges. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateHierarchy(const mnavHierarchyDef* def, mnavHierarchy** hierarchyOut);

Makes a hierarchy with the memory its limits need.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a def not from mnavDefaultHierarchyDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for an allocator with one function, or a limit or cluster side below 1; mnav_errorLimit for one past its MNAV_MAX_ value; mnav_errorCapacity when the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyHierarchy(mnavHierarchy* hierarchy);

Destroys a hierarchy. Called back in from the hierarchy's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the hierarchy is used by one thread at a time.

uint64_t mnavHierarchy_GetMisuse(const mnavHierarchy* hierarchy);

Returns how many calls against the hierarchy were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the hierarchy was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavHierarchy_Build(mnavHierarchy* hierarchy, mnavQuery* query, const mnavNavmesh* navmesh, const mnavQueryFilter* filter, mnavHierarchyReport* reportOut);

Builds the hierarchy for a navmesh as committed and a filter. Each run of tile links along a cluster border, one way, is an entrance whose middle link is a transition; each transition's edges to the transitions leaving the cluster it enters cost what the navmesh search finds within that cluster. Transitions are numbered by tile place, side and position, so the graph does not depend on the order tiles were loaded in. Each off-mesh link, one way, that the filter crosses from one cluster into another is a transition too. A later commit to the navmesh makes the hierarchy stale until it is built again.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorCapacity for more tile slots, transitions or edges than the limits, or a cluster needing more nodes than the context's limit. On an error the hierarchy holds no graph. Also mnav_errorBusy when called back in from the hierarchy's allocator, or from a clearance test whose link generation uses the context, one misuse counted.

Thread safety. Safe from any thread; the hierarchy and the context are used by one thread at a time, no search reads the hierarchy, and no commit runs on the navmesh.

MNAV_NODISCARD MNAV_API mnavResult mnavHierarchy_Update(mnavHierarchy* hierarchy, mnavQuery* query, const mnavNavmesh* navmesh, mnavHierarchyReport* reportOut);

Brings the hierarchy up to the navmesh's last commit. When only polygon areas changed, only the edges of transitions entering the clusters whose tiles changed, and the clusters with transitions out into those tiles, are searched again; when tiles or off-mesh links changed, the hierarchy is built again. The graph is the one a build would make.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a hierarchy built for another navmesh; mnav_errorState for a hierarchy with no graph; mnav_errorCapacity as mnavHierarchy_Build. On an error the hierarchy holds no graph. Also mnav_errorBusy when called back in from the hierarchy's allocator, or from a clearance test whose link generation uses the context, one misuse counted.

Thread safety. Safe from any thread; the hierarchy and the context are used by one thread at a time, no search reads the hierarchy, and no commit runs on the navmesh.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindHierarchicalPath( mnavQuery* query, const mnavHierarchy* hierarchy, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPolygonId endPolygon, mnavPos3 end, mnavPath* pathOut);

Finds a path as mnavQuery_FindPath does, with the hierarchy's filter, through the hierarchy: the start and the end join their clusters' transitions by searches within those clusters, A* over the transitions picks the clusters to cross, and the navmesh search confined to them gives the path. Paths within one cluster, and ends the graph does not reach, take the plain search. Paths are near the cheapest, not always the cheapest. Where routes through the clusters cost the same in the graph, it takes one, the same on every platform, but which one is not promised; the paths they refine to may differ a little in cost.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a point that is not finite, or a hierarchy built for another navmesh; mnav_errorState for a hierarchy with no graph, or a navmesh committed since the build; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis; mnav_errorCapacity for a hierarchy of more transitions than the context's transitions limit; the errors of mnavQuery_FindPath otherwise. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. The search only reads the hierarchy, so any number of contexts may search one at once, as they do a navmesh, while no build or update runs on it and no commit on the navmesh.

linkgen.h

Link generation: off-mesh links for drops off ledges and jumps across gaps, made from a committed navmesh for the host to stage.

static inline mnavLinkGenDef mnavDefaultLinkGenDef(void);

Returns the default generation def: samples every 1 m, drops up to 3 m going both ways up to 0.5 m, jumps up to 2 m, links dropped when walking is within 3 times as far or their ends within 1 m of another's, a snap radius of 0.5 m, costs 2 and 4, kinds mnav_linkDrop and mnav_linkJump, and no clearance test. It carries only a cookie: mnavQuery_GenerateLinks also takes a navmesh and a query context, whose creations checked the version.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_GenerateLinks(mnavQuery* query, const mnavNavmesh* navmesh, const mnavLinkGenDef* def, const mnavTileRange* tiles, const mnavQueryFilter* filter, mnavLinkDef* linksOut, int32_t capacity, int32_t* countOut);

Generates links from the edges of the polygons on a range of tile places that have nothing across them and are not tile sides. Each edge is sampled every spacing meters; a sample tries a drop, landing 2 * radius + 4 * cellSize out from the edge on the highest surface between the agent's step height and dropMax below, and a jump, landing from 2 * radius to jumpMax out at the nearest distance where a surface lies within the step height of the start, the radius, step height and cell size being the navmesh's. Neither lands on the polygon it starts from. A link is kept when the clearance test, if any, passes it, when the navmesh does not already walk from its start to its landing within detour times the straight distance, and when no earlier link in the buffer has both ends within filterDistance of its own. The order is tile place, polygon, edge, sample; the same navmesh gives the same links. A buffer too short holds the same first links as a longer one, but links past it are not filtered against each other, since the context holds no more than the buffer does: the count may then exceed what a long enough buffer keeps, and is always room enough.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a def not from mnavDefaultLinkGenDef, a def value NaN or below 0, a spacing of 0 or below the navmesh's cell size, a detour other than 0 below 1 or past 10^6, a negative kind or one of MNAV_LINK_KINDS or more, a tile range backward, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a def value past its MNAV_MAX_ bound, an infinity included, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorCapacity when more links were generated than the buffer holds, the first capacity written and the count room enough for every link, generation stopping once the count reaches MNAV_MAX_LINKS, which is then the count; mnav_errorLimit when generation stops, the links found so far counted and the first capacity written: at a link past MNAV_MAX_LINKS, the most a navmesh holds, in a buffer holding that many, or at a landing's search box meeting more than MNAV_MAX_LINK_LANDINGS polygons. A call that measures with a short buffer is refused with mnav_errorLimit only where one with room for the count would be too. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time, and no commit runs on the navmesh. The def's clearance test runs on the calling thread, within the call; while it runs, the navmesh's stage calls but mnavNavmesh_StageTile and mnavNavmesh_StageTileRemoval are refused with mnav_errorBusy from any thread.

Flow fields over the navmesh: for every polygon, the cost of its cheapest way to the nearest of a set of goal points and the polygon to go to next, so that any number of agents sharing the goals find their way at the cost of one search.

static inline mnavNavFlowDef mnavDefaultNavFlowDef(void);

Returns the default navmesh flow field def: up to 65,536 polygons, 4,096 tile slots and 4,096 off-mesh links. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateNavFlow(const mnavNavFlowDef* def, mnavNavFlow** fieldOut);

Makes a navmesh flow field with the memory its limits need.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a def not from mnavDefaultNavFlowDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for an allocator with one function or a limit below 1; mnav_errorLimit for a limit past its MNAV_MAX_NAV_FLOW_ value; mnav_errorCapacity when the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyNavFlow(mnavNavFlow* field);

Destroys a navmesh flow field. Called back in from the field's allocator, it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the field is used by one thread at a time.

uint64_t mnavNavFlow_GetMisuse(const mnavNavFlow* field);

Returns how many calls against the navmesh flow field were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the navmesh flow field was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavNavFlow_Begin( mnavNavFlow* field, const mnavNavmesh* navmesh, const mnavTileRange* region, const mnavNavFlowGoal* goals, int32_t goalCount, const mnavQueryFilter* filter);

Begins building the field over the tiles of a region, as mnavNavFlow_Build builds it over all; polygons outside the region are as left out, and only those inside count toward the field's limit. mnavNavFlow_Continue does the work; however it is divided, the field is the same.

Parameters:

Returns: As mnavNavFlow_Build; also mnav_errorInvalid for a region with x0 past x1 or z0 past z1. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavFlow_Continue(mnavNavFlow* field, const mnavNavmesh* navmesh, int32_t polygons, bool* endedOut);

Continues the work begun on a field: settles up to a number of polygons, fewer when the work ends first.

Parameters:

Returns: mnav_success, also when the work had already ended; mnav_errorInvalid for a NULL field or navmesh, fewer than 1 polygon, or a navmesh other than the field's; mnav_errorState for nothing begun, or a navmesh committed to since the work began: begin again. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavFlow_Build(mnavNavFlow* field, const mnavNavmesh* navmesh, const mnavNavFlowGoal* goals, int32_t goalCount, const mnavQueryFilter* filter);

Builds the field for a navmesh and a set of goal points by one search backward from all of them, as path searches price their ways: a polygon stands at the midpoint of the portal it is left by toward the goals, and its cost is the next polygon's plus the walk between them times the next polygon's area cost, with an off-mesh link's cost where the way crosses one. Ties go to the lower cost, then the polygon of the lower slot and index; the same navmesh and goals give the same field on every platform. A polygon with two ways on of equal cost keeps one of them, the same on every platform, but which one is not promised. Goals on polygons the filter leaves out are left out.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a negative count, a goal polygon id never handed out or a goal point not finite, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a goal point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a goal polygon whose tile was replaced or removed; mnav_errorCapacity for a navmesh of more polygons (in the tiles searched), tile slots or off-mesh links than the field's limits. A build allocates nothing. On an error the field holds nothing. Also mnav_errorBusy when called back in from the field's allocator, one misuse counted.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it; the field is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavFlow_GetFlow(const mnavNavFlow* field, const mnavNavmesh* navmesh, mnavPolygonId polygon, mnavPolygonFlow* flowOut);

Reads a polygon's way to the goals from the field.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a navmesh other than the field's or a polygon id never handed out; mnav_errorOutside for a polygon outside the region; mnav_errorState for nothing begun, a navmesh committed to since the work began, or work not yet ended; mnav_errorStale for a polygon whose tile was replaced or removed.

Thread safety. Safe from any thread. Any number of threads may read a field at once while no build runs on it.

MNAV_NODISCARD MNAV_API mnavResult mnavNavFlow_Debug(const mnavNavFlow* field, const mnavNavmesh* navmesh, mnavDebugBuffer* buffer);

Appends an arrow for each polygon of the field that has a way on (mnav_debugFlow): from the mean of the polygon's corners to the midpoint of its portal, or to the takeoff point where the way leaves by an off-mesh link, with two barbs a quarter of its length (at most half a meter) on the ground plane.

Parameters:

Returns: mnav_success, appending nothing when nothing was begun; mnav_errorInvalid for a NULL argument, a navmesh other than the field's, or a buffer with a count out of range, an array missing or an origin not finite; mnav_errorState for a navmesh committed to since the work began, or work not yet ended; mnav_errorCapacity when the buffer filled, its counts saying what the whole needs.

Thread safety. Safe from any thread. Any number of threads may read a field at once while no build runs on it; the buffer is used by one thread at a time.

The navmesh queries read: tiles loaded from baked bytes, staged and committed together, their polygons named by generation-checked ids and linked across the tiles' shared sides.

static inline mnavNavmeshDef mnavDefaultNavmeshDef(void);

Returns the default navmesh def: tiles of the default bake def, the static tier, and limits sized for a large level: 65536 tiles, 32768 links in a tile, 4096 off-mesh links and 256 MiB. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def, with a valid cookie.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavNavmeshDefResult mnavCreateNavmesh(const mnavNavmeshDef* def, mnavNavmesh** navmeshOut);

Makes an empty navmesh from a def: checks the def and keeps a copy, its allocator and its limits.

Parameters:

Returns: mnav_success; mnav_errorInvalid with the setting for a NULL def, a def without its cookie, an allocator with one function, a negative tier or one past mnav_tierDynamic, a limit below 1; mnav_errorLimit with the setting for a limit past its MNAV_MAX_ value; mnav_errorVersion with no setting for a def built against another version of the headers; for a bake def mnavValidateBakeDef refuses, the status it gives with mnav_navmeshSettingBake and its setting; mnav_errorInvalid for a NULL navmeshOut; mnav_errorCapacity when the navmesh does not fit the def's memory limit or the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyNavmesh(mnavNavmesh* navmesh);

Destroys a navmesh, its tiles and everything staged. Called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the navmesh is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavTileResult mnavNavmesh_StageTile(mnavNavmesh* navmesh, const uint8_t* bytes, size_t size);

Loads tile bytes, checking every field as hostile input and the tile's settings against the navmesh's bake def, and stages the tile for the next commit, in place of anything staged at its place before. Queries do not see it until the commit.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument; mnav_errorFormat naming the section and element for malformed bytes, or a tile baked with other settings (the header); mnav_errorVersion for another tile format version; mnav_errorCapacity past the memory limit or when the allocator fails; mnav_errorUnsupported for a tile at a place where one is committed, below mnav_tierDynamic. Also mnav_errorBusy when called back in from the navmesh's allocator, one misuse counted; a link generation's clearance test, or a hierarchy's allocator as it builds on the navmesh, may call it.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time. Staging changes nothing queries read, but it may not run beside another call that stages or commits.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_StageTileRemoval(mnavNavmesh* navmesh, int32_t tileX, int32_t tileZ);

Stages the removal of the tile at a place for the next commit, in place of anything staged there before.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL navmesh; mnav_errorCapacity past the memory limit or when the allocator fails. Also mnav_errorBusy when called back in from the navmesh's allocator, one misuse counted; a link generation's clearance test, or a hierarchy's allocator as it builds on the navmesh, may call it.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time. Staging changes nothing queries read, but it may not run beside another call that stages or commits.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_Commit(mnavNavmesh* navmesh);

Applies everything staged at once: installs and removes the tiles and links every polygon on a changed tile's sides to the polygons across them, adds and removes off-mesh links, and snaps every off-mesh link's ends again. Either all of it applies or, on failure, nothing does and the staged changes stay. A replaced or removed tile's ids become stale, and so do removed links' ids.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL navmesh; mnav_errorCapacity when the tiles would pass the tiles limit, a tile its tileLinks limit, or memory its limit, or when the allocator fails. Also mnav_errorBusy when called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), one misuse counted.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time, so no query may run during a commit.

mnavTier mnavNavmesh_GetTier(const mnavNavmesh* navmesh);

Reads a navmesh's runtime tier.

Parameters:

Returns: Its tier; mnav_tierStatic for NULL.

Thread safety. Safe from any thread. Any number of threads may read it and query at once between commits; none may while a stage or commit call runs.

uint64_t mnavNavmesh_GetMisuse(const mnavNavmesh* navmesh);

Returns how many calls against the navmesh were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the navmesh was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavPolygon_StageArea(mnavNavmesh* navmesh, mnavPolygonId polygon, mnavAreaType area);

Stages a change of a polygon's area, applied at the next commit; mnav_areaNone blocks it. The change lasts while the polygon's tile is loaded, and is dropped when the commit replaces or removes it. Staged again before the commit, the last area counts.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL navmesh, an area out of range or an id never handed out; mnav_errorStale for a polygon whose tile has been replaced or removed; mnav_errorUnsupported for a static navmesh; mnav_errorCapacity when memory runs out. Also mnav_errorBusy when called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), one misuse counted.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time, so no query may run during a stage call.

MNAV_NODISCARD MNAV_API mnavResult mnavPolygon_GetArea(const mnavNavmesh* navmesh, mnavPolygonId polygon, mnavAreaType* areaOut);

Reads a polygon's area as committed.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or an id never handed out; mnav_errorStale for a polygon whose tile has been replaced or removed.

Thread safety. Safe from any thread. Any number of threads may read areas and query at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_GetTile(const mnavNavmesh* navmesh, int32_t tileX, int32_t tileZ, mnavTileId* tileOut);

Finds the tile at a place.

Parameters:

Returns: mnav_success; mnav_errorNotLoaded when no tile is committed there; mnav_errorInvalid for a NULL argument.

Thread safety. Safe from any thread. Any number of threads may find tiles and query at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavStageLink(mnavNavmesh* navmesh, const mnavLinkDef* def, mnavLinkId* linkOut);

Stages an off-mesh link; it is added at the next commit. Its ends snap, at every commit, to the nearest polygon within its radius on the ground and the agent's step in height.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a point with a NaN coordinate, or an edge link whose ends lie at one place on the ground or so near that the square of their distance rounds to 0, a radius, cost or width below 0 or NaN, or a negative kind or one of MNAV_LINK_KINDS or more; mnav_errorLimit for a point farther from the def's origin than bake input may lie (MNAV_MAX_EXTENT_CELLS cells on the ground, MNAV_MAX_HEIGHT_CELLS cell heights up or down), a radius, cost or width past its MNAV_MAX_ bound, an infinity included, or when a crossing would need a slot from MNAV_MAX_LINKS on (left only by slots worn out by 2^32 links each); mnav_errorCapacity when the links' crossings, staged and committed, would pass the links limit, or memory its limit, or when the allocator fails. A refused link is refused whole, none of its crossings taken. Also mnav_errorBusy when called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), one misuse counted.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time, so no query may run while a link is staged.

MNAV_NODISCARD MNAV_API mnavResult mnavStageLinkRemoval(mnavNavmesh* navmesh, mnavLinkId link);

Stages an off-mesh link's removal; it goes at the next commit. A link staged and not yet committed goes at once.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL navmesh or an id never handed out; mnav_errorStale for a link already removed. Also mnav_errorBusy when called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), one misuse counted.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time, so no query may run while a removal is staged.

MNAV_NODISCARD MNAV_API mnavResult mnavLink_StageEnable(mnavNavmesh* navmesh, mnavLinkId link, bool enabled);

Stages enabling or disabling an off-mesh link, applied at the next commit; a link is enabled when added. A disabled link stays snapped but is not crossed.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL navmesh or an id never handed out; mnav_errorStale for a link removed or staged for removal; mnav_errorUnsupported for a static navmesh. Also mnav_errorBusy when called back in from host code a call on the navmesh runs (its allocator, a link generation's clearance test, a hierarchy's allocator as it builds on it), one misuse counted.

Thread safety. Safe from any thread; the navmesh is used by one thread at a time, so no query may run during a stage call.

MNAV_NODISCARD MNAV_API mnavResult mnavLink_IsEnabled(const mnavNavmesh* navmesh, mnavLinkId link, bool* enabledOut);

Reads whether an off-mesh link may be crossed, as committed: a toggle mnavLink_StageEnable stages shows only after the next commit.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or an id never handed out; mnav_errorState for a link staged and not yet committed; mnav_errorStale for a link removed.

Thread safety. Safe from any thread. Any number of threads may read links and query at once between commits; none may while a stage or commit call runs.

MNAV_NODISCARD MNAV_API mnavResult mnavLink_GetState(const mnavNavmesh* navmesh, mnavLinkId link, mnavLinkState* stateOut);

Reads an off-mesh link as committed.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or an id never handed out; mnav_errorState for a link staged and not yet committed; mnav_errorStale for a link removed.

Thread safety. Safe from any thread. Any number of threads may read links and query at once between commits; none may while a stage or commit call runs.

query.h

Queries over a navmesh's committed tiles. Every query reads and never changes the navmesh, and works in world coordinates: meters, right-handed, +Y up.

static inline mnavQueryFilter mnavDefaultQueryFilter(void);

Returns the filter that uses every walkable area at a cost of 1 and every kind of off-mesh link. It carries only a cookie: every call that reads a filter also takes an object whose creation checked the version.

Returns: The filter.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_FindPolygons(const mnavNavmesh* navmesh, mnavPos3 center, mnavVec3 halfExtents, const mnavQueryFilter* filter, mnavPolygonId* polygonsOut, int32_t capacity, mnavFound* foundOut);

Lists the polygons the filter includes whose bounds meet a box: their vertices on the ground and their detail's heights. They come by tile, in place order (x, then z), then by polygon index.

Parameters:

Returns: mnav_success; mnav_errorCapacity when more polygons meet the box than the buffer holds: it holds the first ones and foundOut counts all; mnav_errorInvalid for a NULL argument, a negative capacity, a center or extent that is not finite or a negative extent, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a center more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included.

Thread safety. Safe from any thread. Any number of queries may run at once between commits.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_FindNearest(const mnavNavmesh* navmesh, mnavPos3 point, mnavVec3 halfExtents, const mnavQueryFilter* filter, mnavNearest* nearestOut);

Finds the polygon, among those the filter includes, nearest a point whose nearest point lies within a box round it, and that point. A point over a polygon scores the height it lies beyond the agent's step, any other the distance to the polygon; ties go to the shorter distance, then the tile first by place (x, then z), then the lower polygon index.

Parameters:

Returns: mnav_success, also when no polygon's nearest point lies in the box (the polygon's slot is then 0); mnav_errorInvalid for a NULL argument, a point or extent that is not finite, a negative extent, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included.

Thread safety. Safe from any thread. Any number of queries may run at once between commits.

static inline mnavQueryDef mnavDefaultQueryDef(void);

Returns a query def with 8,192 nodes per search, paths up to 1,000 m, room for a hierarchy of 16,384 transitions, as the default hierarchy def's, and the C library's allocator. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavCreateQuery(const mnavQueryDef* def, mnavQuery** queryOut);

Makes a query context with the memory its limits need.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a def not from mnavDefaultQueryDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for an allocator with one function, fewer than 1 node, a path length not more than 0 or NaN, or fewer than 0 transitions; mnav_errorLimit for more nodes than MNAV_MAX_QUERY_NODES, a path length past MNAV_MAX_PATH_LENGTH, an infinity included, or more transitions than MNAV_MAX_HIERARCHY_TRANSITIONS; mnav_errorCapacity when the allocator fails.

Thread safety. Safe from any thread.

void mnavDestroyQuery(mnavQuery* query);

Destroys a query context. NULL is ignored. Called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), it does nothing and counts one misuse.

Parameters:

Thread safety. Safe from any thread; the context is used by one thread at a time.

uint64_t mnavQuery_GetMisuse(const mnavQuery* query);

Returns how many calls against the context were refused as misuse since it was made: an argument refused with mnav_errorInvalid when the context was the first object the call was given, and a call back in from host code it ran (mnav_errorBusy).

Parameters:

Returns: The count; 0 for NULL.

Thread safety. Safe from any thread. It may be read at any time, also while host code the object runs calls back in.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindPath( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPolygonId endPolygon, mnavPos3 end, const mnavQueryFilter* filter, mnavPath* pathOut);

Searches for the shortest way from a point on one polygon to a point on another: A* over the edges between polygons, its heuristic the straight distance to the end point; ties go to the node made first. A step costs its length times the cost of the area it crosses, and the heuristic is scaled by the cheapest included area's cost; polygons of excluded areas other than the start polygon are not entered. Attached off-mesh links of included kinds are crossed at their declared cost, the heuristic scaled down to the lowest cost per meter among them. The corridor found is pulled tight into a straight path with the funnel algorithm, stretch by stretch between links.

Parameters:

Returns: mnav_success whenever a search ran, however it ended; mnav_errorInvalid for a NULL argument, a point that is not finite, a polygon id that never existed, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a polygon id whose tile has been replaced or removed. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. Any number of contexts may search one navmesh at once between commits.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindShortestPath( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPolygonId endPolygon, mnavPos3 end, const mnavQueryFilter* filter, mnavPath* pathOut);

Searches for the shortest way on the ground from a point on one polygon to a point on another: Polyanya (Cui, Harabor and Grastien, 2017), whose nodes are intervals of portals seen from a root, the start, a corner turned at or an off-mesh link's landing point. Every included area must have the same cost: a step costs its length times that cost, so the way found is the shortest the navmesh allows, measured in x and z, not a way through portal midpoints. Polygons of excluded areas other than the start polygon are not entered. Attached off-mesh links of included kinds are crossed at their declared cost, from the takeoff point to the landing point. Ties go to the node made first. When the nodes run out, the A* search tells whether the end can be reached at all, and an end it cannot reach ends the search as no path. The result is that of mnavQuery_FindPath: the polygons crossed, the turning points, which are the path, and the links crossed; cost and length are those of the points, in three dimensions. A sliced path search in the same context ends.

Parameters:

Returns: mnav_success whenever a search ran, however it ended; mnav_errorInvalid for a NULL argument, a point that is not finite, a polygon id that never existed, a filter not built from mnavDefaultQueryFilter or with a NaN cost or one whose included areas differ in cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a polygon id whose tile has been replaced or removed. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. Any number of contexts may search one navmesh at once between commits.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_BeginPath( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPolygonId endPolygon, mnavPos3 end, const mnavQueryFilter* filter);

Begins a path search to run in slices: the same search as mnavQuery_FindPath, with its own copy of the filter, continued by mnavQuery_ContinuePath and ended by mnavQuery_FinishPath. Whatever the slices, the result is the one mnavQuery_FindPath gives.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a point that is not finite, a polygon id that never existed or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a polygon id whose tile has been replaced or removed. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_ContinuePath(mnavQuery* query, const mnavNavmesh* navmesh, int32_t nodes, bool* endedOut);

Continues a search begun by mnavQuery_BeginPath: closes up to a number of nodes, fewer when the search ends first.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, fewer than 1 node, or a navmesh other than the search's; mnav_errorState for no search begun, or a navmesh committed to since the search began: begin again. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FinishPath(mnavQuery* query, const mnavNavmesh* navmesh, mnavPath* pathOut);

Ends a search begun by mnavQuery_BeginPath and writes its result: as mnavQuery_FindPath's when it has ended; otherwise toward the node nearest the end, its end mnav_pathUnfinished.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a navmesh other than the search's; mnav_errorState for no search begun, or a navmesh committed to since the search began. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_MoveAlongSurface( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPos3 end, const mnavQueryFilter* filter, mnavMove* moveOut);

Moves from a point on a polygon toward a wanted point along the navmesh, as far as the walls allow: a breadth-first walk over the polygons the filter includes whose shared edges meet the circle round the move, in edge order. In the polygon holding the wanted point the move reaches it; otherwise it ends at the point nearest it on the walls met, ties to the wall met first.

Parameters:

Returns: mnav_success whenever the move ran, however it ended; mnav_errorInvalid for a NULL argument, a point that is not finite, a polygon id that never existed or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis (the end's x and z), or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a polygon id whose tile has been replaced or removed. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. Any number of contexts may move on one navmesh at once between commits.

MNAV_NODISCARD MNAV_API mnavResult mnavResetCorridor(mnavCorridor* corridor, mnavPolygonId* buffer, int32_t capacity, mnavPolygonId polygon, mnavPos3 position);

Starts a corridor over a buffer: one polygon, the position and the target both at a point on it.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a capacity below 1 or a point that is not finite.

Thread safety. Safe from any thread; the corridor is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavSetCorridor(mnavCorridor* corridor, const mnavPath* path);

Loads a path into a corridor: its polygons, its first point as the position and its last as the target.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a corridor with no buffer or a capacity below 1, or a path with no polygon or point, a NULL polygons or points, or a path no search gave: arrays other than its context's, or more polygons, points or links than the search gave; mnav_errorStale for a path a later search of its context has replaced; mnav_errorCapacity when the path has more polygons than the corridor's buffer. The corridor is unchanged on any failure.

Thread safety. Safe from any thread; the corridor is used by one thread at a time, and the path's context, which it reads, by no other thread meanwhile.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_CheckCorridor(const mnavNavmesh* navmesh, const mnavCorridor* corridor, const mnavQueryFilter* filter, int32_t* validCountOut);

Counts a corridor's leading polygons that are still current, of areas the filter includes, and joined to the one before by an edge, a tile link or an off-mesh link of a kind it includes. Fewer than all means the corridor needs trimming there and replanning.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a corridor not well formed or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a corridor whose position or target lies more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included.

Thread safety. Safe from any thread. Any number of threads may check corridors at once between commits.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindCorridorCorners(mnavQuery* query, const mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavCorners* cornersOut);

Finds a corridor's straight path from its position to its target: the funnel over the portals between its polygons.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a corridor not well formed or polygons not joined; mnav_errorLimit for a corridor whose position or target lies more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis; mnav_errorStale for a polygon whose tile has been replaced or removed; mnav_errorCapacity for a corridor of more polygons than the context's node limit. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindCorridorAreas( mnavQuery* query, const mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavCorners* cornersOut, mnavAreaRun* runsOut, int32_t capacity, int32_t* countOut);

Finds the areas along a corridor's straight path: the corners mnavQuery_FindCorridorCorners gives, which replace the context's last ones, and a run where the path starts, one wherever it crosses into a polygon of another area, and one where it lands from each off-mesh link, in order. Hosts change gait or sound at a run's start; a path's areas are its corridor's, once loaded with mnavSetCorridor.

Parameters:

Returns: As mnavQuery_FindCorridorCorners; also mnav_errorInvalid for a NULL countOut, a negative capacity or NULL runs with a positive one, and mnav_errorCapacity when the runs do not fit, the first capacity of them written. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

static inline mnavSteerDef mnavDefaultSteerDef(void);

Returns a steering def of 3.5 m/s, slowing within 1 m of the target, arriving within 0.1 m, anticipating turns. Built in the program, so that it carries the version of the headers the program includes.

Returns: The def.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavSteer(const mnavCorners* corners, const mnavSteerDef* def, mnavSteering* steeringOut);

Steers along a corridor's corners: toward the next corner, or swinging wide of it, at the def's speed, slowing within its slowing distance of the target by the distance left along the corners over it; stopped within the arrival distance of the target or of the next link's takeoff. Keeps no state: call it each step with the corners mnavQuery_FindCorridorCorners gives, feed the velocity to avoidance, and limit acceleration and move the agent yourself. The corners may be the caller's own: their arrays are the caller's memory, read only within pointCount and linkCount, every point checked; a link's point is compared, never followed.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, corners with no points or a link count below 0, or a def not from mnavDefaultSteerDef; mnav_errorVersion for one built against another version of the headers; mnav_errorInvalid also for a def value below 0 or NaN, or a corner not finite; mnav_errorLimit for a speed past MNAV_MAX_STEER_SPEED or a distance past MNAV_MAX_STEER_DISTANCE, an infinity included.

Thread safety. Safe from any thread.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_MoveCorridor(mnavQuery* query, mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavPos3 wanted, const mnavQueryFilter* filter, mnavMove* moveOut);

Moves a corridor's position along the surface toward a wanted point (mnavQuery_MoveAlongSurface from its first polygon) and merges the polygons walked into its start: it keeps its polygons from the farthest one the walk passed, led to by the walk.

Parameters:

Returns: As mnavQuery_MoveAlongSurface; also mnav_errorInvalid for a corridor not well formed, mnav_errorLimit for one whose position or target lies more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, and mnav_errorCapacity when the merged corridor would outgrow its buffer, which leaves it unchanged. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. So is the corridor.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_MoveCorridorTarget( mnavQuery* query, mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavPos3 wanted, const mnavQueryFilter* filter, mnavMove* moveOut);

Moves a corridor's target along the surface toward a wanted point (mnavQuery_MoveAlongSurface from its last polygon) and merges the polygons walked into its end: it keeps its polygons up to the first one the walk passed, then the rest of the walk.

Parameters:

Returns: As mnavQuery_MoveCorridor. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. So is the corridor.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_ShortcutCorridor(mnavQuery* query, mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavPos3 toward, const mnavQueryFilter* filter, bool* shortenedOut);

Shortens a corridor where the agent can see ahead: casts a ray from its position toward a point, usually a corner a few ahead; when the ray reaches it, the polygons it crossed replace the corridor's start up to the last corridor polygon it passed, if that is fewer.

Parameters:

Returns: As mnavQuery_Raycast; also mnav_errorInvalid for a corridor not well formed or a NULL shortenedOut, and mnav_errorLimit for one whose position or target lies more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. So is the corridor.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_ReplanCorridor( mnavQuery* query, mnavCorridor* corridor, const mnavNavmesh* navmesh, mnavVec3 halfExtents, const mnavQueryFilter* filter, mnavPath* pathOut);

Plans a corridor again from its position to its target and loads the path found: from its first and last polygons while they are current, else from the polygons nearest the position and the target within a box round each. A corridor whose position or target finds no polygon is left as it was, the path's end saying why.

Parameters:

Returns: mnav_success whenever the corridor was looked at; mnav_errorInvalid for a NULL argument, a corridor not well formed or a half size below 0 or not finite; mnav_errorLimit for a corridor whose position or target lies more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis; mnav_errorCapacity when the path has more polygons than the buffer, which leaves the corridor as it was; the errors of mnavNavmesh_FindNearest and mnavQuery_FindPath otherwise. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. So is the corridor.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindGridPath(mnavQuery* query, const mnavGrid* grid, mnavCell start, mnavCell end, const mnavQueryFilter* filter, mnavGridPath* pathOut);

Finds the cheapest path between two cells of a grid, moving to the 8 neighbours and never across a blocked corner: a diagonal step needs both cells beside it open. A step costs its length times the mean of its two cells' area costs. When every area the filter includes costs the same, the search is jump point search, else A*; both keep the context's node limit and path length, and end as mnavQuery_FindPath does, with the path to the cell nearest the end when the end is not reached. A grid search ends any sliced search.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a grid with no areas, a side below 1 or a cell size not more than 0 or not finite, a cell outside the grid, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a side past MNAV_MAX_GRID_SIDE or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavPolygon_GetHeight(const mnavNavmesh* navmesh, mnavPolygonId polygon, double x, double z, double* heightOut);

Reads the height of a polygon's detail surface at a point on the ground.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a coordinate not finite or a polygon id never handed out; mnav_errorLimit for a coordinate more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis; mnav_errorOutside for a point outside the polygon on the ground; mnav_errorStale for a polygon whose tile has gone.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindWallDistance( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId polygon, mnavPos3 center, double radius, const mnavQueryFilter* filter, mnavNearestWall* nearestOut);

Finds the nearest wall to a point within a radius on the ground, searching from its polygon across the edges that come within the radius, off-mesh links aside. An edge is a wall where no polygon the filter includes lies across it: a tile side with no tile loaded beyond, and the parts of a side no polygon of the tile beyond covers, are walls. A wall counts only on the center's floor: its point nearest the center lies no more than the agent's step height below the center's height on its polygon, and no more than the agent's height above, for the agent the navmesh's tiles are baked for; the walls of a floor over or under the center are left out. A wall exactly the radius away lies within it; of walls at the same distance it gives one, the same on every platform, but which one is not promised.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument, a point or radius not finite, a negative radius, a polygon id never handed out, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorStale for a polygon whose tile has gone; mnav_errorLimit for a center more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, a radius past MNAV_MAX_QUERY_DISTANCE, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindWalls(mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId polygon, mnavPos3 center, double radius, const mnavQueryFilter* filter, mnavWall* wallsOut, int32_t capacity, mnavWallsFound* foundOut);

Lists the walls within a radius of a point on the ground, nearest first, for avoidance's segment obstacles: the search and the walls of mnavQuery_FindWallDistance, whose wall is the first listed: only walls on the center's floor, as it counts them. Walls at the same distance keep the order the search meets them in, the same on every platform.

Parameters:

Returns: mnav_success; mnav_errorCapacity when more walls lie within the radius than the buffer holds: it holds the nearest and foundOut counts all; mnav_errorInvalid for a NULL argument, a negative capacity, a point or radius not finite, a negative radius, a polygon id never handed out, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorStale for a polygon whose tile has gone; mnav_errorLimit for a center more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis, a radius past MNAV_MAX_QUERY_DISTANCE, or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavNavmesh_FindRandomPoint(const mnavNavmesh* navmesh, uint64_t seed, const mnavQueryFilter* filter, mnavRandomPoint* pointOut);

Picks a point uniformly over the ground area of every polygon the filter includes, from a seed: the same seed and navmesh give the same point on every platform. The point lies on the polygon's detail surface. The call reads every polygon twice.

Parameters:

Returns: mnav_success; mnav_errorInvalid for a NULL argument or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included.

Thread safety. Safe from any thread. Any number of threads may read the navmesh at once while no commit runs on it.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_FindRandomPointAround( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId polygon, mnavPos3 center, double radius, uint64_t seed, const mnavQueryFilter* filter, mnavRandomPoint* pointOut);

Picks a point reachable from a center: a polygon the walls search reaches within the radius, by ground area, then a point uniformly on it, which may lie beyond the radius by up to the polygon's size.

Parameters:

Returns: As mnavQuery_FindWallDistance; also mnav_errorLimit when a polygon clipped to the circle, its 32-gon, has more than MNAV_MAX_CLIP_CORNERS corners, which rounding alone can cause. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_CheckReachable( mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPolygonId endPolygon, mnavPos3 end, const mnavQueryFilter* filter, mnavPathEnd* endOut);

Tells whether the end can be reached from the start: the path search with its limits, without a path made. mnav_pathFound when it can, mnav_pathNone when it cannot, or the limit that stopped the search before it could tell.

Parameters:

Returns: As mnavQuery_FindPath. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time.

MNAV_NODISCARD MNAV_API mnavResult mnavQuery_Raycast(mnavQuery* query, const mnavNavmesh* navmesh, mnavPolygonId startPolygon, mnavPos3 start, mnavPos3 end, const mnavQueryFilter* filter, mnavRay* rayOut);

Casts a ray along the navmesh on the ground from a point on a polygon toward an end point: polygon to polygon through the first edge it crosses, until it reaches the end point, meets a wall (an edge into a polygon the filter excludes is a wall too) or a tile side with no tile loaded, or crosses as many polygons as the context's node limit. Where it leaves through a corner, it goes on through an edge that leads on, the lowest-numbered first; at a corner where two walls meet, the normal is one of theirs, the same on every platform, but which one is not promised.

Parameters:

Returns: mnav_success whenever the ray was cast, however it ended; mnav_errorInvalid for a NULL argument, a point that is not finite, a polygon id that never existed, or a filter not built from mnavDefaultQueryFilter or with a NaN cost; mnav_errorLimit for a point more than MNAV_MAX_QUERY_DISTANCE from the navmesh's origin on an axis (the end's x and z), or a filter cost past MNAV_MIN_AREA_COST or MNAV_MAX_AREA_COST, an infinity included; mnav_errorStale for a polygon id whose tile has been replaced or removed. Also mnav_errorBusy when called back in from host code a call using the context runs (a link generation's clearance test, a hierarchy's allocator as it builds), one misuse counted.

Thread safety. Safe from any thread; the context is used by one thread at a time. Any number of contexts may cast on one navmesh at once between commits.