Hey Mikko,
I have a question about NavMeshTesterTool::recalc(). I've been using it to generate paths and after doing some performance analysis I'm finding the following figures on a fairly long path in a mesh of around 70k polys:
- findPath() takes 0.515 ms.
- the smoothing process detailed below takes 7.16 ms.
As you can imagine, optimizing smoothing became my #1 priority and thus my first step is understanding the code. I have a high level understanding of what the code flow is, but my question for you is why. I'm used to seeing a pathfind, then a funnel implementation, however in the case of Recast I'm seeing a lot more code. fixupShortcuts() looks pretty self explanatory, but I'm very confused with the purpose of steps 2.2, 3 and 4. What is this code doing? It just seems to walk along a polygon, tiny distances at a time, returning path waypoints at each. My end result path for a path that is only a few meters long (for example) has dozens of waypoints when I'd have expected only 2 or 3 in a typical use case.
Below is my high level analysis of this code? Is my understanding correct? What is the concept behind the below code? What is it trying to do and what problems was the small iterations looking to solve? This work to me seems unnecessary, so I'd love some background on why the complexity was added.
Thanks and I look forward to hearing back from you soon.
My high level understanding of what the pathfind code path does:
- Calls nav query findPath() to return an unsmoothed path of each polygon along the path.
- It then goes through each poly and calls getSteerTarget().
- This calls findStraightPath() (i.e., the funnel algorithm) to return to me what appears to be the first iteration along the funnel algorithm.
- The results of this are iterated through and we stop as soon as we find something that's SLOP away. (question, why stop here?)
- This position is returned as the target.
- This target position is then turned into a movement delta via STEP_SIZE / len where len equals the distance to the target pos. (question, why do we limit the target position in this way?)
- We compute a tiny move target from this and call moveAlongSurface(). (question, why moveAlongSurface instead of raycast?)
- moveAlongSurface() then checks a distance half way out and selects it if it's valid, or finds the wall and calculates distance as needed. (question, why only half way, why not move all the way to the target if we can?)
- We then call fixupCorridor() which is unclear but might be splicing in polygons that the smoothing visited?
- We then call fixupShortcuts() which as the comment suggests, finds shortcuts if able.
- This whole thing continues until we have reached the end of our path.