Duplicate vertex indices in recast graph with Tiles



I’m writing a custom path post processing algorithm (MonoModifier), and i’m running into an issue.

One of the steps of the algorithm needs to know which corners two adjacent GraphNodes share. The code’s pretty straight forward:

// n0 and n1 are adjacent corners in the graph sent to Apply
private static void FindSharedCorners(RecastGraph graph, TriangleMeshNode n0, TriangleMeshNode n1, List<Vector3> result) {

    if (n0.v0 == n1.v0 || n0.v0 == n1.v1 || n0.v0 == n1.v2) {
        result.Add((Vector3) graph.GetVertex(n0.v0));
    if (n0.v1 == n1.v0 || n0.v1 == n1.v1 || n0.v1 == n1.v2) {
        result.Add((Vector3) graph.GetVertex(n0.v1));
    if (n0.v2 == n1.v0 || n0.v2 == n1.v1 || n0.v2 == n1.v2) {
        result.Add((Vector3) graph.GetVertex(n0.v2));


The problem here is that if I generate the Recast Graph with tiles, I sometimes get no shared corners. Checking closer, it seems like the TriangleMeshNodes have corners with the same positions, but different indices.

Is that intentional? Does tiled graphs have several indices for the same vertexes? Or is that something that can always happen, and I’m only seeing in tiled graphs?

I want to avoid comparing the node’s positions (this modifier runs a lot), but right now it seems like I have to do that.



Tiles are independent, so each tile has its own set of vertices that are not shared with any other tiles. This is done to ensure that tiles can be replaced and recalculated independently of each other.

Luckily for you however the methods that you look for already exist.
You may want to have a look at TriangleMeshNode.SharedEdge and TriangleMeshNode.GetPortal.

The GetPortal call takes 2 lists, it will add one vertex to each list which is the left and right side of the edge that was shared. In case the nodes only partially share an edge (which can happen at the border between two tiles) it will add the part of the edges that both nodes share. It will also output the edge index in the same way as the SharedEdge method.
This method is used internally for the funnel modifier, which is why it isn’t that well documented unfortunately.



Thanks for that! That both removed a few bugs, and allowed me to delete quite a bit of code.