Navigation Plugin V2 is here!

Awesome to see you here, @isaac-mason!!

That would be an awesome collab with @roland :grinning_face_with_smiling_eyes:

1 Like

I’ve viewed the examples on navcat.dev, and they’re pretty cool.

2 Likes

Hey @isaac-mason! Great to have you here!

I believe maintaining backward compatibility of the interface is the top priority. More advanced or specialized scenarios can always be addressed by accessing navcat’s functionality directly.

I’m excited to collaborate and hear your thoughts on how we can align babylon.js’s navigation system with navcat in a practical way.

Let’s bring @Cedric into the discussion as well.

4 Likes

@Panuchka I know your project pushes the NavigationPlugin quite a bit, would love to get your input on this discussion as well!

2 Likes

https://navcat.dev/ examples are awesome! It looks very fast as well!

The goal of current Navigation API in Babylon is to be able to get crowds and navmesh in a few calls. I like this approach to get comething moving on screen quickly and then get more depth in the API and use cases. Babylon navigation was made a long time ago when WASM and compilation of native code was a bit more obscure. (same for performance). If navcat.dev is easy to integrate in a JS environment , I guess integration on Babylon would be limited to a few things like debug draw, mesh conversion,… something else?

1 Like

I believe maintaining backward compatibility of the interface is the top priority. More advanced or specialized scenarios can always be addressed by accessing navcat’s functionality directly.

That is fair enough :slightly_smiling_face:

I’m excited to collaborate and hear your thoughts on how we can align babylon.js’s navigation system with navcat in a practical way.

For sure, are you and others on the babylonjs discord or somewhere else @roland? Maybe we can discuss there more easily.

The goal of current Navigation API in Babylon is to be able to get crowds and navmesh in a few calls. I like this approach to get comething moving on screen quickly and then get more depth in the API and use cases.

If navcat.dev is easy to integrate in a JS environment , I guess integration on Babylon would be limited to a few things like debug draw, mesh conversion,… something else?

@Cedric I can understand the benefit of that :slightly_smiling_face:

And I think your assessment on integrating navcat in a babylonjs project right now, without any navigation plugin work, is right.

I can see a few paths for serving babylon.js users:

  • A) As you mentioned, just use navcat directly, it’s library agnostic. The examples use three.js but there’s nothing prescriptive about that in core. Debug helpers would need to be implemented, and manual extraction of positions and indices from babylon structures (if they are the source) would need to be implemented. After this, you can reference navcat examples and bring what you need into your project.
  • B) Create a navcat/babylonjs package with small helpers for A), so bjs users don’t need to repeat that work
  • C) Create an implementation of the babylonjs navigation interface that uses navcat. For this, we could either:
    • Start from a copy of the crowd implementation in navcat examples and host that in bjs (same for anything else not in core atm needed for the plugin?), which could potentially give flexibility to make the navigation APIs more cohesive with other ideas in the babylonjs engine. I’m not well placed to comment on whether that would be of great advantage to bjs or not.
    • Collaborate on a “navcat-addons” package that hosts abstractions like “crowd” and “tilecache” equivalents. Or make some APIs good and flexible enough together to put in core. Use these in a then slimmer bjs navigation interface implementation.

Also +1 to the point that these are not mutually exclusive!

2 Likes

My Discord account got terminated a few weeks ago because of long inactivity :smiley: If you prefer Discord, I can hop back in anytime! Just not right now, I’m about to dive into the Navcat integration for babylon.js, and my desk’s already packed with work.

Let me talk it over with the team. @Cedric, I’ll dig into Navcat and put together a proposal, we can open the discussion after that. Are you OK with that?

@isaac-mason Thanks a lot!

2 Likes

Discord is probably easiest for me for quick responses or if you’re keen for a back and forth chat. You can DM me, and or find me and a few others following navcat and recast-navigation-js on the webgamedev discord, in the game-ai channel Web Game Dev. Otherwise I’ll keep an eye here and also on github issues.

I’ll wait to hear from you then, don’t hesitate to reach out! :slightly_smiling_face:

2 Likes

Small update from my side. I’ve started working on a “navcat/blocks” package entrypoint that will contain higher level abstractions like “crowd”, “path corridor”, “preset generators”, “flow field pathfinding” etc.

12 Likes

Awesome !!!

2 Likes

Thank you for providing this new version of recast.js.:slight_smile:
I might have discovered a bug in babylonjs.addons.min.js(v8.33.4),maybe we should add a forced type conversion for TileCacheMeshProcess like this?

//@@@@create TileCacheMeshProcess instance
    var h=c?rt(t):u?it(t):tt(t);
    if(h.tileCacheMeshProcess)
        h.tileCacheMeshProcess=new (Qe().TileCacheMeshProcess)((h.tileCacheMeshProcess));

Ortherwise it will cause a nullpointer error in recast.js.
Meanwhile,should we change the demo code in this page

if (avgY > 1.5) {
            polyAreas.set(i,STAIRS_AREA)
            polyFlags.set(i,STAIRS_FLAG)
            //polyAreas[i] = STAIRS_AREA;//it dosen't work
            //polyFlags[i] = STAIRS_FLAG;
        } else {
            polyAreas.set(i,DEFAULT_AREA)
            polyFlags.set(i,WALK_FLAG)
            //polyAreas[i] = DEFAULT_AREA;
            //polyFlags[i] = WALK_FLAG;
        }

@roland Before I found the notes on V2 I was working on integrating NavCat. I rounded it out with your v2 code. It’s frickin’ awesome how nicely Babylon and NavCat have enabled me to get something working.

Also I love the navMesh code already supports thininstances I thought that was gonna be a whole thing :smiley:

Some very small notes I can contribute back :

1. ThinInstances that have a fully zero’d out matrix breaks NavCat

They cause navCat’s calculateMeshBounds to return a bounds object with NaNs.

This is likely to bite people as one heavily caveated (see below comments) way of ‘deleting’ a thinInstance is to just zero out it’s buffer data with thinInstanceSetMatrixAt.

To mitigate this I hacked up your getPositionsAndIndices code to include an unrolled loop style isAllZero check

        if (mesh.hasThinInstances) {
          worldMatrices.push(worldMatrix);
          const thinMatrices = (mesh as Mesh).thinInstanceGetWorldMatrices();
          for (let instanceIndex = 0; instanceIndex < thinMatrices.length; instanceIndex++) {
            const tmpMatrix = new Matrix();
            const thinMatrix = thinMatrices[instanceIndex];
            thinMatrix.multiplyToRef(worldMatrix, tmpMatrix);

            // Don't include fully zero'd matrices because they break NavCat's calculateMeshBounds
            const m = tmpMatrix.m;
            const isMatrixAllZero =
              m[0] === 0 &&
              m[1] === 0 &&
              m[2] === 0 &&
              m[3] === 0 &&
              m[4] === 0 &&
              m[5] === 0 &&
              m[6] === 0 &&
              m[7] === 0 &&
              m[8] === 0 &&
              m[9] === 0 &&
              m[10] === 0 &&
              m[11] === 0 &&
              m[12] === 0 &&
              m[13] === 0 &&
              m[14] === 0 &&
              m[15] === 0;

            if (!isMatrixAllZero) {
              worldMatrices.push(tmpMatrix);
            }
          }
        } else {
          worldMatrices.push(worldMatrix);
        }
  1. Placing meshes directly on top of a ground/plane generates a lot of ‘reachable’ islands inside the pillars if they’re placed directly on top
    This is half observation half question as I’m not familiar with navmeshes : I’m not sure what if any issues / perf this might cause. Not a major thing, maybe worth putting in the docs

Ground plane
(top left original scene, right is aggregate mesh before sent to navCat, bottom left is navMesh result)

vs a box with 1 depth causing overlap

1 Like

I’m not sure where this comes from as a “generally accepted way”.

What is the consequence of zeroing a matrix, is it effectively equivalent to setting the scale to 0?

I would rather decrement thinInstanceCount as listed in the doc, after copying a matrix if you’re not removing the last element. That would avoid executing the vertex shader for your deleted instances.

navcat (and recast from which the navmesh creation algorithm is taken) does not work with “solid” shapes but only treats a list of triangles. So the voxellization process may create holes, depending on your parameters (typically voxel size and walkable radius). Isaac did a great job at illustrating the process in navcat’s docs.

Checked and you’re right, it’s stated as a heavily caveated possibility, not an accepted way

Thankyou for the info, I’m deep in those docs at the moment figuring out why a flat meshified tilemap isn’t classed as walkable (bit offtopic but if anyone has any ideas :folded_hands:):slight_smile:

Your response doesn’t quite answer my question though : I wasn’t sure what if any issues / perf this might cause. My gut and a quick goggle suggests avoiding islands may lead to better performance.

Apart from increased memory usage, you might encounter worse performance with polygon queries (such as findClosestPoint), but no difference with path queries, as the A* algorithm is only traveling through connected polygons. If your world is big, using tiles would already improve the general performance of polygon queries and limit the potential overhead with only a few more polygons per tile.

Also this is definitely offtopic so if you need more help with navcat, you should post on navcat’s github or the web game dev’s discord where Isaac is also present (link above in his message)