Archive 17/01/2023.

NavigationMesh: Can’t Build Mesh

I3DB

I saw a previous post here.

And read the documentation here.

I’m starting with this sample code.

And note that when the planeNode code in the sample is removed or shifted lower to execute after the navMesh.Build() statement, then the sample code starts generating this error:

System.Exception: Could not build navigation mesh tile data. 

So it appears the NavigationMesh component is scouring the Scene node and must find at least one static model. The documentation states:

NavigationMesh collects geometry from its child nodes that have been tagged with the Navigable component.

And the sample code does indeed have one statement that adds a navigable component, but right to the scene. If that component is removed, no error is generated by navMesh.Build(), but no navigation takes place either.


Now, my issue is that I’ve copied this code and put it into another project.

Now matter what I do, the ‘Could not build navigation mesh tile data’ message appears, often many times. With or without the planeNode code inserted.

Just trying to figure out why.

The navigation does mostly work even with this error, but somehow is not very smooth. The sample works fairly smoothly. So it seems something is wrong with my code/setup.

If the NavigationMesh is added to a node, rather than the scene, then the error comes once. If added to the scene, the error is generated about 10 times.

I3DB

If I add the NavigationMesh to a child node of Scene, and add the Navigable component to the Scene.

The errors go away … but no navigation. Perhaps that’s in my code.

Still don’t see the difference between the sample code, which adds NavigationMesh to the Scene, and my code.

Can anyone point to a link for the NavigationMesh.cpp file? Just trying to understand what is happening. Between lack of documentation, and lack of info in exceptions and errors, hoping a review of the code might help.

Modanung

Neither do I. :wink:
Got repo?

Modanung

Sure: Source/Urho3D/Navigation/NavigationMesh.cpp

lezak

It looks like there is not enough surface area in Your scene to build a navmesh tile. For example- You won’t be able to build navmesh on default settings when there is only 1x1 plane in the scene, but if You scale up this plane or decrease cellsize and agent radius in navmesh settings it will build. In the sample You linked, created plane is scaled to 20x20 so it provides surface to build navmesh.

I3DB

@lezak @Modanung Yes, it appears to be the surface area and sizing of tiles, and perhaps the actual navigation is working unusually based on scaling on one or more nodes. The cpp code has a warning about node scaling that doesn’t make it up to the SharpReality interface…

The sample that @Egorbo did purposely did NOT use Hololens room scan data rather stuck in that plane as a workaround. He left a note in the code too.

Once I got the plane working, have been trying to create the navMesh using the node that is holding the Hololens room scan data. That room scan is not just a flat plan but has walls and ceiling and in general stuff all over (because the room I’m standing in is somewhat cluttered).

It would seem I can pass in environmentNode (holds the scan data), but no navigation occurs in that case. The issue is the CrowdAgentReposition event won’t fire. Everything else appears to be working, and this line of code does execute as expected, and the pathPos is set to the correct spot selected by the user. So this executes

crowdManager.SetCrowdTarget(pathPos, Scene);

but no event is triggered, so the mutants remain in place. If I pass in other nodes rather than the Scene, at times it works based on which node has the navMesh and which nodes are set as navigable.

But if I change the lines of code needed, as an example

navMesh = environmentNode.CreateComponent<NavigationMesh>();

then

environmentNode.CreateComponent<Navigable>();

then

navMesh = environmentNode.GetComponent<NavigationMesh>();
var pathPos = navMesh.FindNearestPoint(hitPos.Value, new Vector3(0.1f, 0.1f, 0.1f));
crowdManager.SetCrowdTarget(pathPos, environmentNode);

in this case the CrowdReposition event never fires. So not sure if there is no way to navigate around the objects in the environmentNode (for instance due to some height limitations) or some other issue.

Even if I put a plane in the environmentNode and put the mutants on the plane, and adjust the plane a bit higher than the floor, still no reposition event occurs.

Modanung

Have you tried drawing some debug geometry?

I3DB

Yes, have tried it, but no debug geometry is painted with this code.

In other samples, the debug geometry works fine. Not sure what is up with this, the code is executed, but no debug geometry appears. Before troubleshooting why no debug geometry appears, have been just making changes throughout the sample code to try to get some clue on what’s happening with navigation without relying upon debug geometry.

If I use a plane, all works fine, if I try to get it to use the environmentNode (which has all the scanned room data), then nothing happens in regards to navigation. There is never a reposition event generated. The code to reposition is called, but no idea what happens or fails to happen next.

This error started appearing:

System.Exception: Navigation mesh must first be built fully before it can be partially rebuilt.
lezak

If there is no debug geometry, it means that navmesh is not build/don’t have any tile and propably that’s why agents don’t move.
What is Your scene layout with scanned data? Try creating navmesh component on the scene root node and add navigable to the scene root or the environmentNode.
Another thing:

this will work only if nodes with crowd agents are children of environmentNode and in sample You’ve linked they’re not.
Other things that may help (if agents still don’t move after navmesh is properly build):
-check if agents are added to the crowd (CrowdAgent::IsInCrowd());
-listen to CrowdAgentFailure Event.

I3DB

I got it working, and this appears to be what did it, but also @lezak did make armyNode a child of environmentNode too, but the bounding box with build really helped make the navigation work, when it was just 20, not very good navigation, but upping to 50 and it is working nicely :

navMesh.Build();
navMesh.Build(new BoundingBox(-Vector3.One * 50f, Vector3.One * 50f));

Lots of the’ERROR: Could not build navigation mesh tile data’ exceptions are thrown. But the navigation works fairly well, and the mutants avoid obstacles, meaning the mutants walk around furniture in the room, as I didn’t purposely create anything, just used the room scan data in the environmentNode. When Scene is used rather than environmentNode, it requires the plane, and none of the exceptions are thrown on navMesh.Build().

Still no debug geometry is seen. @

Experimenting with the navMesh.TileSize, for instance going from 2 to 1, increases the number of the exceptions. I’m not sure which of the values are important in regards to what is happening.

navMesh.CellSize = 0.2f;
navMesh.CellHeight = 0.02f;
navMesh.DrawOffMeshConnections = true;
navMesh.DrawNavAreas = true;
navMesh.TileSize = 1;
navMesh.AgentRadius = 0.05f;

Here’s some of the lines of changed code, primarily changed Scene to environmentNode:

navMesh = environmentNode.CreateComponent<NavigationMesh>();
//this plane is a workaround 
//TODO: build a navmesh using spatial data
//var planeNode = Node.CreateChild();
//var plane = planeNode.CreateComponent<StaticModel>();
//plane.Model = CoreAssets.Models.Plane; 
//plane.SetMaterial(spatialMaterial);
//planeNode.Scale = new Vector3(20, 1, 20);
//planeNode.Position = hitPos.Value;

environmentNode.CreateComponent<Navigable>();

navMesh.Build();
navMesh.Build(new BoundingBox(-Vector3.One * 50f, Vector3.One * 50f));

crowdManager = Scene.CreateComponent<CrowdManager>();

armyNode = environmentNode.CreateChild();

also

navMesh = environmentNode.GetComponent<NavigationMesh>();
var pathPos = navMesh.FindNearestPoint(hitPos.Value, new Vector3(0.1f, 0.1f, 0.1f));
crowdManager.SetCrowdTarget(pathPos, environmentNode);

If I could figure out the reasons for debug geometry not showing and the tile exceptions it would be perfect. As @lezak pointed out, they may share the same root cause.

I3DB

If the naveMesh.TileSize = 2 is commented out which then uses the default of 128, the can’t create tile errors go away. But no debug geometry either.

Also, not much comes through on the CrowdAgentFailure, unless I adjust the agentradius and cellsize settings. But when the event is generated, no useful info comes. Just the node and position, but I couldn’t glean any info on why the failure occurred or the nature of the failure.

lezak

Have You created debug renderer in the scene?

Isn’t minimal tile size 16? Try increasing tile size (lets say to 64 or 128) and if that doesn’t help, decrease cell size, but basically try tweaking values, because it’s hard to give accurate values without knowing geometry.

I3DB

I can’t find info on minimal tile size. Trying to get a basic understanding of Tiles and tile size and cells and cell size and what is the difference between a tile and a cell.

Have looked in places like here for info.

I mentioned default of 128, because if it’s not set that is the default value that appears.

In terms of these settings that were set as shown in the sample code:

navMesh.CellSize = 0.2f;
navMesh.CellHeight = 0.02f;
navMesh.DrawOffMeshConnections = true;
navMesh.DrawNavAreas = true;
navMesh.TileSize = 2;
navMesh.AgentRadius = 0.05f;

Of those settings, some experimentation in my case (sharpreality + hololens) the AgentRadius is important and when increased causes the navigation to stop. Also cellsize and cellheight.

There are settings on the crowd agent in that sample too.

var agent = mutantNode.CreateComponent<CrowdAgent>();
agent.Height = 0.2f;
agent.NavigationPushiness = NavigationPushiness.Medium;
agent.MaxSpeed = 0.4f;
agent.MaxAccel = 0.4f;
agent.Radius = 0.03f;
agent.NavigationQuality = NavigationQuality.High;

So a quick review shows the agent.Radius set at 0.03f, but on the mesh is set at .05. So wondering if these should be the same.

I suspect the errors and poor navigation results in some of the cases I’ve tested can be quickly fixed with a basic understanding of some of these settings.

What is cellsize and agent radius? And tile size?

I’m assuming the agent radius for both cases, is a value used in calculating the navigation path and uses the radius as a sphere used during the calculation to ensure the agent can get to that point given it’s size. And that radius should be the same.

@lezak Have not specifically added a debug renderer, as started with this sample code which also doesn’t. Assuming the debug renderer was setup in the StereoApplication or it’s initialization. Haven’t tracked it down yet. It’s SharpReality api. In the sample code the debug renderer is also not working.

EDIT: Found the issue with debug renderer, thanks @lezak, it was missing an essential line as is the sample code. Once this was added, the debug works fine, and have to say, for tracking down issues with navigation mesh, the debug REALLY HELPS.

Scene.CreateComponent<DebugRenderer>();
I3DB

Ok, here’s what I’ve found for my application using hololens with sharp reality.

The hololens mapping takes in the number of triangles to map the space with. Too few and navigation doesn’t work well. When I upped it to > 2000, the navigation improved.

Cellsize of 0.08 seemed the best balance between errors and navigation expediency and success. The agent setting on NavigationPushiness also plays a role. In my case there is no happy medium between the settings Medium and High and None loses all crowd control, and the agents end up as one occupying the same space. At high, the navigation result is good but the end result suffers as they group too closely, at medium the navigation suffers and in the end they’re grouped too loosely, and radius settings didn’t seem to help that much.

Tile size didn’t seem to make much difference except in the number of errors that appear. I only used values of 16 and up. At 64 everything seems to work nicely, same at 32, 96, and 128. At 128 no errors, at 32 a lot. At 64 six errors at 72 eight errors, at 96 three errors. Frankly I couldn’t make any sense of this except there is generally a linear relationship, but can figure out why errors go up going from 64 to 72, when in most other cases increasing tile size reduced the error count.

Overall, this was way too time consuming. There needs to be some sort of useful documentation on the relationship between cell size, tile size and errors being generated.

Also, even the slightest bit of info on why the error is at all generated.

The debug was immensely helpful and quickened the pace once it worked. Should have got this working first.

I3DB

These are the settings that ended up:

navMesh = environmentNode.CreateComponent<NavigationMesh>();
environmentNode.CreateComponent<Navigable>();
navMesh.CellSize = .08f;
navMesh.CellHeight = .05f;
navMesh.TileSize = 96;
navMesh.AgentRadius = 0.03f; 
navMesh.Build();
crowdManager = Scene.CreateComponent<CrowdManager>();
var parameters = crowdManager.GetObstacleAvoidanceParams(0);
parameters.VelBias = 0.5f; 
parameters.AdaptiveDivs = 7;
parameters.AdaptiveRings = 3;
parameters.AdaptiveDepth = 3;
crowdManager.SetObstacleAvoidanceParams(0, parameters);

and

var agent = mutantNode.CreateComponent<CrowdAgent>();
agent.Height = 0.15f;
agent.NavigationPushiness = NavigationPushiness.Medium;
agent.MaxSpeed = 0.4f;
agent.MaxAccel = 0.4f;
agent.Radius = 0.05f;
agent.NavigationQuality = NavigationQuality.High;
Eugene

Yeah. Urho almost directly exposes Detour/Recast library, and this library is working by magic. I’m not 100% sure that even author(s) completely understand it.

I3DB

Yes, I sort of came to that conclusion aftersearching for and finding the author’s code.

The downfall of this for Hololens development is the room scan is a big portion of the value added. While it does work, there is quite a bit of smoothing of objects rather than recognition they shouldn’t be in the navmesh.

For instance an actual foot stool in my room becomes a modest sloping hill that the mutants run over, rather than running around. Perhaps there is a height setting for that, but not sure. Actual stairs end up as a slope, which is ok, and mutants can go up them, but the foot stool seemed too high. A chair near the footstool wasn’t navigable.

Also, there are various lumps and small hills that appear in the navigation mesh that don’t appear in the room scan. So if there is no debug geometry visible, the mutants will randomly start going up an invisible incline, and it takes away from the experience. If the debug geometry is on, it’s clear why the mutants go uphill, but not clear why the slop is there in all cases.

But, in general, the navigation does work, it seemed more an issue with the CrowdAgent getting all the mutants to the right place in a visually pleasing way, and the CrowdAgent is heavily affected by the NavigationMesh settings, rather than it not working.

@Egorbo also had issues and ended up just sticking in a plane, rather than figuring out a way to use the room scan. So at least there was some progress.

Here’s a dev blog on this library http://digestingduck.blogspot.com/