Changelog

All notable changes to this project are recorded here, grouped as Added, Changed, Fixed, Removed and Security. The project uses Semantic Versioning. Before 1.0.0, any release may change the API, the ABI and the tile formats.

1.2.0 (2026-11-05)

This release makes mnavQuery_GenerateLinks find jumps across gaps on a navmesh baked with an agent radius of 0. Links change only on such a navmesh; at any radius above 0 they are the same.

Changed

1.1.3 (2026-11-05)

This release gives the navmesh queries a range: a point, end, center or radius more than MNAV_MAX_QUERY_DISTANCE (1e100 m) from the navmesh's origin is now refused with mnav_errorLimit. Such input used to give wrong results. Results within the range do not change.

Fixed

1.1.2 (2026-11-05)

This release stops mnavQuery_FindShortestPath from opening nodes past its path length toward an end far away. No result changes for a caller that keeps the contract.

Changed

Fixed

1.1.1 (2026-11-05)

This release makes MNAV_NODISCARD the [[nodiscard]] attribute in GCC 14's C23 mode, so that a C program built with GCC 14 is warned when it drops a status the library returns.

Fixed

1.1.0 (2026-11-04)

This release changes which walls the wall queries report on a navmesh with floors over each other, and makes a query context keep the last path a search gave, so that mnavSetCorridor checks a path against it. A query context holds 76 bytes more per node. Wall distances and lists change only where a wall of another floor was reported, and steering changes only where a corner lies past 2^500 of the origin.

Added

Changed

Fixed

1.0.1 (2026-11-03)

This release fixes the corridor of a shortest path that ran straight through a corner where polygons meet. Only such a path's polygons change; its points, cost and length do not, and no other result changes.

Changed

Fixed

1.0.0 (2026-11-03)

This release settles the API: from 1.0.0 there is no 2.0.0. Tile format 4 and flight tile format 3 keep their version, and a later 1.z library reads every tile a 1.y wrote. No code, tile bytes, fingerprints or results change from 0.8.6.

Changed

0.8.6 (2026-11-03)

This release fixes what an audit of the debug draws found: a path with a point that is not finite was drawn instead of refused. No results change.

Fixed

0.8.5 (2026-11-03)

This release fixes what an audit of the corridor code found: a path with NULL arrays crashed mnavSetCorridor, and corridors with a position or target that is not finite were used instead of refused. No results change.

Fixed

0.8.4 (2026-11-02)

This release fixes what a coverage pass found: a query context made with an allocator that sets only one of its two functions released memory to the wrong allocator. Paths, tiles and their formats are unchanged.

Fixed

0.8.3 (2026-11-02)

This release fixes what an audit of the steering code found: corners with a link count below 0 were steered instead of refused. Paths, velocities, tiles and their formats are unchanged.

Fixed

0.8.2 (2026-11-02)

This release fixes what an audit of the flow fields found: a repair given two very long lists skipped its check that their cells lie in the grid. Paths, flow fields, tiles and their formats are unchanged.

Fixed

0.8.1 (2026-11-02)

This release fixes what an audit of the corridor calls found: a replan took a broken search box whenever it did not need the box. Paths, tiles and their formats are unchanged.

Fixed

0.8.0 (2026-11-02)

This release fixes what an audit of the detail mesh and of the flight tile loader found. A polygon edge took at most 20 height samples, and a slanted edge's samples could snap to a gap wider than detailSampleDistance, so long edges and tile sides were sampled more widely than asked, silently. Now an edge takes up to 41 samples and a segment more where snapping leaves a gap, and every edge still sampled more widely is counted in the bake report. The flight loader refuses a tile at a place no bake writes.

The tile format rises to 4, so tiles baked by 0.7.0 are refused with mnav_errorVersion and must be rebaked. The bake generation rises to 6. Polygons and their links are unchanged, so paths cross the same polygons; heights read from the detail surface change along edges that now carry more samples. Tiles grow by about 4% at the default def, and more with a small detailSampleDistance and a detailMaxError near 0. Flight tiles and their format are unchanged.

Fixed

0.7.0 (2026-11-01)

This release fixes what an audit of the status codes and a differential check of tile sides found. A walkable region one cell thin is no longer dropped by the bake, so neighboring tiles agree on their shared side; this raises the bake generation to 5. A debug buffer counts triangles and lines, not indices, and link generation gives a measuring call room at the link limit instead of a refusal.

No tile format rises, so tiles baked by 0.6.0 load as they are. Every tile's fingerprint differs from a new bake's, so a host that keeps tiles by fingerprint rebakes them once. Paths, corridors, flow fields, links and velocities are unchanged, except on tiles with a walkable region one cell thin, which now gets a polygon where it had none.

Fixed

0.6.0 (2026-11-01)

This release brings maul-nav in line with the family rulings of the 1.0.0 reviews. Every enumeration typedef is a 32-bit integer, and every counter is named for what it counts. A bake now keeps a very short edge length or sample distance in force, which raises the bake generation to 4. A commit or destroy no longer frees a tile while its ids are still live.

No tile format rises, so tiles baked by 0.5.0 load as they are. Their fingerprints differ from a new bake's, so a host that keeps tiles by fingerprint rebakes them once. Paths, corridors, flow fields and velocities are unchanged, except on tiles baked with a maxEdgeLength below one cell or a detailSampleDistance below a sixteenth of a cell, whose polygons or detail now differ.

Changed

Fixed

0.5.0 (2026-10-30)

This release finishes the API review for 1.0.0. A call that fills a caller's array now zeroes it over its capacity when it fails, and a refused debug call leaves its buffer as it was. The bake def's setting values carry the def's name, and the family's hash takes a 64-bit byte count.

On success nothing changes: tile bytes, fingerprints, paths, debug geometry and velocities are the same, and no tile format rises, so tiles baked by 0.4.0 load as they are.

Changed

0.4.0 (2026-10-30)

This release settles the last API changes planned before 1.0.0. - Navmeshes and flight volumes are made from defs of their own. - Any number of query contexts can search one hierarchy at once. - A refused bake input is named by its kind and index. - The grid flow field is mnavGridFlow. - A call refused as busy from host code writes none of its outputs.

Tile bytes, fingerprints, paths, flow fields and velocities do not change, and no tile format rises: tiles baked by 0.3.0 load as they are.

Changed

Old New
mnavFlowField mnavGridFlow
mnavFlowFieldDef, mnavDefaultFlowFieldDef mnavGridFlowDef, mnavDefaultGridFlowDef
MNAV_FLOW_FIELD_DEF_COOKIE MNAV_GRID_FLOW_DEF_COOKIE
mnavCreateFlowField, mnavDestroyFlowField mnavCreateGridFlow, mnavDestroyGridFlow
mnavFlowField_Begin, _Continue, _Update, _Build, _GetFlow, _Debug, _GetMisuse mnavGridFlow_Begin, _Continue, _Update, _Build, _GetFlow, _Debug, _GetMisuse
mnavFlow mnavCellFlow
MNAV_MAX_FLOW_CELLS MNAV_MAX_GRID_FLOW_CELLS
MNAV_MAX_NAVFLOW_POLYGONS, _TILES, _LINKS MNAV_MAX_NAV_FLOW_POLYGONS, _TILES, _LINKS

0.3.0 (2026-10-30)

The whole API takes the Maul family's naming rule, so most functions have new names and 25 take their arguments in a new order (the table under Changed). Avoidance velocities change: they are binary32 now, a velocity held to the maximum speed no longer passes it, and an agent that only its own speed holds back no longer steps aside. Tile bytes, fingerprints and paths do not change, and no tile format rises: tiles baked by 0.2.0 load as they are.

Added

Changed

Old New Parameters
mnavResultName mnavGetResultName
mnavGetAvoidanceMisuse mnavAvoidance_GetMisuse
mnavAvoid mnavAvoidance_Avoid
mnavAvoid3D mnavAvoidance_Avoid3D
mnavDebugAvoidance mnavAvoidance_Debug
mnavDebugAvoidance3D mnavAvoidance_Debug3D
mnavGetBakerMisuse mnavBaker_GetMisuse
mnavBakeTile mnavBaker_BakeTile
mnavBakeTile2D mnavBaker_BakeTile2D
mnavCopyBakedTile mnavBaker_CopyTile
mnavBakeTileCached mnavBaker_BakeTileCached
mnavRebuildTile mnavBaker_RebuildTile
mnavGetTileIndexMisuse mnavTileIndex_GetMisuse
mnavGetTileCacheMisuse mnavTileCache_GetMisuse
mnavDropCachedTile mnavTileCache_DropTile
mnavGetTileCacheBytes mnavTileCache_GetBytes
mnavDebugNavmesh mnavNavmesh_Debug
mnavDebugLinks mnavNavmesh_DebugLinks
mnavDebugCorridor mnavNavmesh_DebugCorridor
mnavGetFlightBakerMisuse mnavFlightBaker_GetMisuse
mnavBakeFlightTile mnavFlightBaker_BakeTile
mnavCopyFlightTile mnavFlightBaker_CopyTile
mnavGetFlightVolumeMisuse mnavFlightVolume_GetMisuse
mnavStageFlightTile mnavFlightVolume_StageTile
mnavStageFlightTileRemoval mnavFlightVolume_StageTileRemoval
mnavCommitFlight mnavFlightVolume_Commit
mnavGetFlightTile mnavFlightVolume_GetTile
mnavIsFlightOpen mnavFlightVolume_IsOpen
mnavFlightRaycast mnavFlightVolume_Raycast
mnavCheckFlightPath mnavFlightVolume_CheckPath
mnavFindNearestFlightPoint mnavFlightVolume_FindNearestPoint
mnavDebugFlight mnavFlightVolume_Debug
mnavFindFlightPath mnavQuery_FindFlightPath
mnavBeginFlightPath mnavQuery_BeginFlightPath
mnavContinueFlightPath mnavQuery_ContinueFlightPath
mnavFinishFlightPath mnavQuery_FinishFlightPath
mnavGetFlowFieldMisuse mnavFlowField_GetMisuse
mnavBeginFlowField mnavFlowField_Begin (field, grid, region, goals, goalCount, filter)
mnavContinueFlowField mnavFlowField_Continue
mnavUpdateFlowField mnavFlowField_Update
mnavBuildFlowField mnavFlowField_Build (field, grid, goals, goalCount, filter)
mnavFlowAt mnavFlowField_GetFlow
mnavDebugFlowField mnavFlowField_Debug
mnavGetHierarchyMisuse mnavHierarchy_GetMisuse
mnavBuildHierarchy mnavHierarchy_Build
mnavUpdateHierarchy mnavHierarchy_Update
mnavFindHierarchicalPath mnavQuery_FindHierarchicalPath
mnavGenerateLinks mnavQuery_GenerateLinks (query, navmesh, def, tiles, filter, linksOut, capacity, countOut)
mnavClearanceFn mnavClearanceFunction a function type (see above)
mnavGetNavFlowMisuse mnavNavFlow_GetMisuse
mnavBeginNavFlow mnavNavFlow_Begin (field, navmesh, region, goals, goalCount, filter)
mnavContinueNavFlow mnavNavFlow_Continue
mnavBuildNavFlow mnavNavFlow_Build (field, navmesh, goals, goalCount, filter)
mnavNavFlowAt mnavNavFlow_GetFlow
mnavDebugNavFlow mnavNavFlow_Debug
mnavGetNavmeshMisuse mnavNavmesh_GetMisuse
mnavStageTile mnavNavmesh_StageTile
mnavStageTileRemoval mnavNavmesh_StageTileRemoval
mnavCommit mnavNavmesh_Commit
mnavGetTier mnavNavmesh_GetTier
mnavGetTile mnavNavmesh_GetTile
mnavStageArea mnavPolygon_StageArea
mnavGetArea mnavPolygon_GetArea
mnavStageLinkEnabled mnavLink_StageEnable
mnavGetLink mnavLink_GetState
mnavGetQueryMisuse mnavQuery_GetMisuse
mnavFindPolygons mnavNavmesh_FindPolygons (navmesh, center, halfExtents, filter, polygonsOut, capacity, foundOut)
mnavFindNearest mnavNavmesh_FindNearest (navmesh, point, halfExtents, filter, nearestOut)
mnavFindRandomPoint mnavNavmesh_FindRandomPoint (navmesh, seed, filter, pointOut)
mnavCheckCorridor mnavNavmesh_CheckCorridor (navmesh, corridor, filter, validOut)
mnavGetHeight mnavPolygon_GetHeight
mnavFindPath mnavQuery_FindPath (query, navmesh, startPolygon, start, endPolygon, end, filter, pathOut)
mnavFindShortestPath mnavQuery_FindShortestPath (query, navmesh, startPolygon, start, endPolygon, end, filter, pathOut)
mnavBeginPath mnavQuery_BeginPath (query, navmesh, startPolygon, start, endPolygon, end, filter)
mnavContinuePath mnavQuery_ContinuePath
mnavFinishPath mnavQuery_FinishPath
mnavMoveAlongSurface mnavQuery_MoveAlongSurface (query, navmesh, startPolygon, start, end, filter, moveOut)
mnavCorridorCorners mnavQuery_FindCorridorCorners (query, corridor, navmesh, cornersOut)
mnavCorridorAreas mnavQuery_FindCorridorAreas (query, corridor, navmesh, cornersOut, runsOut, capacity, countOut)
mnavMoveCorridor mnavQuery_MoveCorridor (query, corridor, navmesh, wanted, filter, moveOut)
mnavMoveCorridorTarget mnavQuery_MoveCorridorTarget (query, corridor, navmesh, wanted, filter, moveOut)
mnavShortcutCorridor mnavQuery_ShortcutCorridor (query, corridor, navmesh, toward, filter, shortenedOut)
mnavReplanCorridor mnavQuery_ReplanCorridor (query, corridor, navmesh, halfExtents, filter, pathOut)
mnavFindGridPath mnavQuery_FindGridPath (query, grid, start, end, filter, pathOut)
mnavFindWallDistance mnavQuery_FindWallDistance (query, navmesh, polygon, center, radius, filter, nearestOut)
mnavFindWalls mnavQuery_FindWalls (query, navmesh, polygon, center, radius, filter, wallsOut, capacity, foundOut)
mnavFindRandomPointAround mnavQuery_FindRandomPointAround (query, navmesh, polygon, center, radius, seed, filter, pointOut)
mnavCheckReachable mnavQuery_CheckReachable (query, navmesh, startPolygon, start, endPolygon, end, filter, endOut)
mnavRaycast mnavQuery_Raycast (query, navmesh, startPolygon, start, end, filter, rayOut)

Fixed

0.2.0 (2026-10-28)

Tile bytes, fingerprints, paths and velocities do not change, and no tile format rises: tiles baked by 0.1.0 load as they are. Flow fields change for one call sequence (see Fixed).

Added

Changed

(#135) - Breaking: mnav_errorTier is removed. A staged tile, area change or link toggle that the navmesh's tier does not allow is refused with mnav_errorUnsupported. (#138) - Breaking: host code may not call into the objects of a running call. That is an allocator, a baker's clock or a link generation's clearance test. Such a call is refused with mnav_errorBusy when it returns a status, does nothing when it returns nothing, and counts one misuse. This holds for the object the host code serves and for the other objects the running call uses: the baker, tile index and tile cache of a bake or rebuild, and the context and navmesh of a hierarchy's build or update. It also holds for the release of an object's own memory. A clearance test or a hierarchy's allocator may still call mnavStageTile and mnavStageTileRemoval. Before, such a call could read freed memory. (#141, #145, #147) - Breaking: a call refused with mnav_errorInvalid counts one misuse on the first object it is given. Input geometry a bake refuses and its report names counts none. (#148) - Breaking: a place outside what an object covers is mnav_errorOutside, not mnav_errorInvalid, and counts no misuse. This covers: - mnavGetHeight for a point off the polygon - mnavFlowAt and mnavNavFlowAt for a cell or polygon outside the field's region - mnavIsFlightOpen, mnavFindFlightPath and mnavBeginFlightPath for a point below or above the flight volume

A host that handled these as mnav_errorInvalid handles mnav_errorOutside. The outputs stay as they were, but mnavIsFlightOpen sets openOut to false. (#148, #150) - The troubleshooting table lists the new numbering and results. The getting-started and baking pages say what host code may call.

Fixed

0.1.0 (2026-10-27)

Changed

Fixed

0.0.4 (2026-10-24)

Changed

0.0.3 (2026-10-24)

Changed

Fixed

0.0.2 (2026-10-24)

Fixed

0.0.1 (2026-10-24)

The first release: navmesh and flight volume baking, queries, corridors, flow fields and avoidance, with results that are bit-identical on every platform, compiler and worker count.

Added

Changed