How to properly create a navmesh for Babylonjs (babylon-navigation-mesh library)

Hi, I’m using wanadev’s Babylon-navigation-mesh library which is “A toolkit to navigate on a mesh with BABYLON.js”. The dev provides a tutorial as well on how to use it.

The library works fine with the navmesh the dev provided in the demo, but at the time of using my own generated navMesh, the library can’t seem to find points within my geometry, failing to find paths for moving the agent.

I was wondering if there are any gotchas or hard requirement for creating a navmesh that can be used with these sorts of libraries. I know the issue is in my geometry because the provided in the demo one works fine. Also the navmesh that the creator made was done using the now deprecated Blender’s game logic mode that I don’t think is available anymore.

I generated my navMesh using Unity + Blender following this tutorial:

Is there a chance the gltf export messes with the geometry? is anybody else in the babylon community using this plugin that could identify what I might be doing wrong? thanks!

Attaching my navmesh glb file just in case it helps
NavMesh.zip (1.1 KB)

@Cedric is the king of our navmesh and might be able to help :slight_smile:

Hi @hvnsNight

The .obj you provided is not correct. there is only vertex positions in the file but the face description mentions normal and uv. Can you please check your export is correct.
To verify it’s a valid .obj, you can try to open it with the sandbox : https://sandbox.babylonjs.com/

2 Likes

Ah gotcha, thanks for clarifying, I generated my navMesh from Unity using some script i found through he tutorial i linked:

using System.IO;
using System.Text;
using UnityEditor;
using UnityEditor.SceneManagement;
using UnityEngine;
using UnityEngine.AI;

// Obj exporter component based on: http://wiki.unity3d.com/index.php?title=ObjExporter

public class ExportNavMeshToObj : MonoBehaviour
{

    [MenuItem("Custom/Export NavMesh to mesh")]
    static void Export()
    {
        NavMeshTriangulation triangulatedNavMesh = NavMesh.CalculateTriangulation();

        Mesh mesh = new Mesh();
        mesh.name = "ExportedNavMesh";
        mesh.vertices = triangulatedNavMesh.vertices;
        mesh.triangles = triangulatedNavMesh.indices;
        string filename = Application.dataPath + "/" + Path.GetFileNameWithoutExtension(EditorSceneManager.GetActiveScene().name) + " Exported NavMesh.obj";
        MeshToFile(mesh, filename);
        print("NavMesh exported as '" + filename + "'");
        AssetDatabase.Refresh();
    }

    static string MeshToString(Mesh mesh)
    {
        StringBuilder sb = new StringBuilder();

        sb.Append("g ").Append(mesh.name).Append("\n");
        foreach (Vector3 v in mesh.vertices)
        {
            sb.Append(string.Format("v {0} {1} {2}\n", v.x, v.y, v.z));
        }
        sb.Append("\n");
        foreach (Vector3 v in mesh.normals)
        {
            sb.Append(string.Format("vn {0} {1} {2}\n", v.x, v.y, v.z));
        }
        sb.Append("\n");
        foreach (Vector3 v in mesh.uv)
        {
            sb.Append(string.Format("vt {0} {1}\n", v.x, v.y));
        }
        for (int material = 0; material < mesh.subMeshCount; material++)
        {
            sb.Append("\n");
            //sb.Append("usemtl ").Append(mats[material].name).Append("\n");
            //sb.Append("usemap ").Append(mats[material].name).Append("\n");

            int[] triangles = mesh.GetTriangles(material);
            for (int i = 0; i < triangles.Length; i += 3)
            {
                sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));
            }
        }
        return sb.ToString();
    }

    static void MeshToFile(Mesh mesh, string filename)
    {
        using (StreamWriter sw = new StreamWriter(filename))
        {
            sw.Write(MeshToString(mesh));
        }
    }
}

However, it does seem like the script doesn’t generate normals/uv data/required data for a navmesh on the final exported mesh. Is there any alternative that you might know to properly generate a navmesh? Recast is not an option for me (unless I could use it to just generate my navMesh file in 3d mesh format somehow to use with the library in question)

I searched the forum and found another user @Null with a similar use case, using the same javascript library I’m trying to use: Alternative Navigation Mesh Solution.

Thanks!

try replacing

sb.Append(string.Format("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\n", triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));

with

sb.Append(string.Format("f {0} {1} {2}\n", triangles[i] + 1, triangles[i + 1] + 1, triangles[i + 2] + 1));

Thank you! here’s attempt 2, I tried it on the sandbox and it displays properly :slight_smile: navmeshv2.zip (898 Bytes)

However, at the time of importing along with some level geometry, I’m still unable to trigger the pathfinding algorithm to find a path… I import the navmesh into blender the following way:

  • import the navmesh exported from Unity with the below script
  • flip the x axis to accommodate for the mesh being wrong from the export
  • enable backface culling
  • flip triangles by going to mesh>Normals>Flip
  • export as .glb along with the scene geometry

I then add it to babylon to use with this library I mentioned in my first post. The algorithm doesn’t detect the geometry and doesn’t produce a path unfortunately :frowning:

Hi @hvnsNight
Sorry for the delay
I’ve importer your .obj and used the PG from the doc. I didn’t get any issue while creating the navmesh:

navmesh with custom mesh | Babylon.js Playground (babylonjs.com)

Do I miss something?

1 Like

Thanks for your reply, it seems I got misunderstood. I’m not using recast, but wanadev’s Babylon-navigation-mesh library due to my environment’s limitation with using recast. It is with that library that I’m attempting to use my mesh but it doesn’t work.

I see! Can you ping the creators then?

1 Like

I’ve solved the issue! the problem was that my agent was too high in the y axis compared to where the navmesh was (so the agent was not in the navmesh plane). That’s why the path wasn’t found. A very dumb mistake, but hope this helps others :slight_smile:

1 Like