NavMeshPathFinder always finds a path

I have successfully implemented everything to use the AI library.

My terrain area consists of 3 heightmaps with varying terrain heights up to near verticle, a blender scaled terrain model and a floating, rotating box object thrown in for testing paths around a object.

I use the NavMeshGenerator.java file to generate the mesh from the 4 areas and box.

I use the mouse to determine where I want the spatial to navigate to.

The problem:

No matter where I click, inside or outside the navmesh, NavMeshPathFinder always returns true when pathfinder.computePath(target); returns.

This leads to the spatial trying to climb targets that are impossible to climb and are outside the navmesh. The generated navmesh looks fine to me based off the parameters entered. Clicking inside the mesh will generate complex paths around objects, up ramps, etc. Clicking outside the mesh also generates a path though.

Shouldn’t the NavMeshPathfinder return false if someone clicks outside the navmesh?

Are we supposed to sanity check the target vector3f before sending it to be processed by pathfinder.computePath(target); ?

I see this method being called and wondered why is this exact number 3.4E+38f; being used also.

/**
     * Find the closest cell on the mesh to the given point
     * AVOID CALLING! not a fast routine!
     * @param point
     * @return 
     */
    public Cell findClosestCell(Vector3f point) {
        float closestDistance = 3.4E+38f;
        float closestHeight = 3.4E+38f;
        boolean foundHomeCell = false;
        float thisDistance;
        Cell closestCell = null;

        // oh dear this is not fast
        for (Cell cell : cellList) {
            if (cell.contains(point)) {
                thisDistance = Math.abs(cell.getHeightOnCell(point) - point.y);

                if (foundHomeCell) {
                    if (thisDistance < closestHeight) {
                        closestCell = cell;
                        closestHeight = thisDistance;
                    }
                } else {
                    closestCell = cell;
                    closestHeight = thisDistance;
                    foundHomeCell = true;
                }
            }

            if (!foundHomeCell) {
                Vector2f start = new Vector2f(cell.getCenter().x, cell.getCenter().z);
                Vector2f end = new Vector2f(point.x, point.z);
                Line2D motionPath = new Line2D(start, end);

                ClassifyResult Result = cell.classifyPathToCell(motionPath);

                if (Result.result == Cell.PathResult.ExitingCell) {
                    Vector3f ClosestPoint3D = new Vector3f(
                            Result.intersection.x, 0.0f, Result.intersection.y);
                    cell.computeHeightOnCell(ClosestPoint3D);

                    ClosestPoint3D = ClosestPoint3D.subtract(point);

                    thisDistance = ClosestPoint3D.length();

                    if (thisDistance < closestDistance) {
                        closestDistance = thisDistance;
                        closestCell = cell;
                    }
                }
            }
        }

        return closestCell;
    }
1 Like

Don’t know if it helps but here is a pic of the navmesh and the spatial running to get to the target which is outside the navmesh on a veticle cliff.

1 Like

I only know that i had an issue where it returned a list of nulls for Paths and such things so there might indeed be a bug. If the path generated for outside the mesh is valid though, its on your side.

Are you using MeFisto94s fork on github or are you using 3.0?

1 Like

No, Im using the one from jMonkeyEngine Contributions and 3.1 stable.

Most likely. Not sure how I could cause this behavior though.

1 Like

Well I’m not sure if the navmesh pathfinder will stop you from clicking outside the navmesh. It will simply find a path through the mesh to the location within the mesh that is closest to the point you clicked and the path will then have that point you clicked as end point.

1 Like

Yes, if I remember the returned path always contains the start and end points even if there is no path between them.

1 Like

You can check if the distance from the goal-point to the clicked-point is less than X (a tolerance distance).

1 Like

I am asking because that should not even compile for 3.1 and lead to runtime errors^^

Also check that ^. If this is not the case, then I wonder how the pathfinder would know your other mesh (which would lead me to believe you somehow picked the wrong mesh, scaling issues and thelike)

1 Like

I updated the library to java 8.1. I left the heap classes alone for now to make sure things worked first before changing them.

There is only one navmesh created for the 4 terrains and box and everything matches the contours in scale and location. I changed the MavMeshGenerator method terrain2mesh to use WorldTranslation also.

I see. This may be what’s allowing it to advance past the navmesh. That end point is the vector3f I fed the pathfinder and is being returned so BetterCharacterControl takes over at the closet navmesh point and advances the spatial to the end point is what it sounds like is happening.

This is being done.

Sounds like I need to determine if the end point is outside the navmesh since it will always be returned and clear the path when spatial reaches the last point inside the navmesh if I am understanding everyone correctly.

1 Like

Well the thing is you will always have to supply the actual Vector3f location as the navmesh can basically only tell if stuff can go from cell to cell. Add to that things like NPCs avoiding each other, objects, animations etc. – your final clicking and pathing logic definitely won’t end with the NavMesh anyway :slight_smile:

But yeah afaicremember the NavMesh should allow you to find that out pretty easily.

1 Like

Ok I finally got this worked out but wanted to run this by everyone before I call it solved.

I went ahead and actually used mefisto fork of the AI but still had same problem. I also found the documentation for the criteria that this is all based off of and was able to fine tune my navMesh. Had no effect on the problem.

I still could not get any methods in the library to return false when my endpoint was outside the navMesh.

That being the case the only option was to use warpInside() method to always make sure the endPoint was inside the mesh and this is what finally worked.

Changing this line in the computePath() method inside the NavMeshPathfinder class keeps the spatial inside the mesh at all times. It works on extremely complex terrains, even when there is an island navMesh selected.

//        goalPos3d = goal;
        goalPos3d = this.warpInside(goal);

I haven’t seen any “unintended features” popup yet so if anyone can think of one let me know please.

Edit: My desired result for the navigation was that if the user clicked outside the navMesh, a path would be generated to the nearest point inside the mesh to where they clicked.

Edit: You don’t have to change the line, just warp the endpoint itself before passing it to the NavMeshPathfinder…

2 Likes