isaac-mason / recast-navigation-js

JavaScript navigation mesh construction, path-finding, and spatial reasoning toolkit. WebAssembly port of Recast Navigation.
https://recast-navigation-js.isaacmason.com
MIT License
273 stars 25 forks source link

computePath of straight line is detouring to hit steiner-points #439

Open OdinvonDoom opened 1 month ago

OdinvonDoom commented 1 month ago

The problem:

Shown in the image is the output of Recast generateSoloNavMesh()... getDebugNavMesh(). The triangulation seems fine (if not a little needlessly heavy across some edges, but I'll presume it's necessary), but the issue comes when I try t navigate nearby one of these steiner-points using the output of navmeshQuery.computePath, and for some reason the path funneling is not going through all the triangles, but detouring to the point.

RecastFailing - pathing onto steiner point

Background:

I'm making a 2D game, and trying to adapt Recast for it, given it's high regard and inadequacies of other navigation libraries, but I'm having a lot of trouble due to lacking sufficient usage guides/documentation, so I'm likely doing something wrong.

I've built a boundary polygon in the "Tiled" 2D map creation program, clipping off some outer edges and inner holes using "js-angusj-clipper", then triangulating the result with "poly2tri".

The resulting set of triangles, I manually convert to 3D, y-axis-up, right-handed space, and into the requisite flat arrays of positions and indices as required by Recast's generateSoloNavMesh, getting the result seen above from there.

Of course, given the amount of adaptation being done, I'm likely doing something wrong, but I can't find much to go off unless I happened to be using Three.js, which I am not.

Likely point of failure:

  1. The "Delaunay" triangulation of "Poli2Tri" likely does not produce the same sort of polygonal divisions (size/structure) that would be found in a Three.js mesh, resulting in bad input?
  2. The navmesh holes being worked out of the positions and indices ahead of calling generateSoloNavMesh is perhaps a problem? Though I really have not seen anywhere else how to define a "hole" in Recast.
  3. My initial efforts to use generateSoloNavMesh failed on the entire map, so I tried filtering to just the first few triangles, and found success to only a given point (13 tris = success, 14 = failure), later realizing that the more I increased the cellSize, the more triangles could successfully complete generateSoloNavMesh, so now without truly understanding why, I "successfully" create the navmesh with navMeshGeneratorConfig: cs: 1.5.

I'm truly trying to read everything I can to understand how Recast works and why I'm having these troubles, but I just can't find anything truly explanatory for direct usage not involving Three.js or some other major engine.

I can maybe convert my map polygon to Three's ShapeGeometry if that will help with Recast compatibility, but I really have no clue what might be the problem.

isaac-mason commented 1 week ago

Hey @OdinvonDoom! Apologies for the late reply.

I should call out that while some have probably had success using recast for 2d games, it's not the most optimal tool for 2d use cases. The way recast constructs navigation meshes has unnecessary complexity and overhead for 2d inputs.

Perhaps a simpler library like nav2d could better serve your needs, see:


If you choose to proceed with using recast for your use case, I would suggest as a next step visualising the navigation mesh build process intermediates to see if any input / build process issues become more obvious with intermediates.

Some quick things you could try:

The github issues and google discussions on the main recastnavigation repo are a good place to look for existing similar issues, you may find some more information there:


I can maybe convert my map polygon to Three's ShapeGeometry if that will help with Recast compatibility, but I really have no clue what might be the problem.

The core of recast-navigation-js is entirely agnostic to three.js. The only requirements for input are the below:

The input positions and indices should adhere to OpenGL conventions:

  • Use the right-handed coordinate system
  • Indices should be in counter-clockwise winding order
  • The positions and indices arguments should be flat arrays of numbers

If you are able to post a minimal reproduction, myself or another library user may be able to take a look at your issue 🙂