[SOLVED] a problem in using navMesh (downward face normals)

I made the navmesh in blender and export it to ogreXml and convert it to j3o.
in the blender, I check the normal of face and edge and vertexes and all of them was upward.
but in JME when I loaded NavMesh it shows some warning like this:
Warning, normal of the plane faces downward!!!

1- how can I solve this problem?
2- is there any way to upward the normals in JME in runtime?
3- is not there any other library of pathfinding for JME?

This kinda stuff is user contributed or found in external libraries or written by the game creator themselves.

jme3-ai is just someones contribution, not an official jme module.

I would suggest you learn about recast4j or some other ai as jme3-ai is basic ai and works great for a simple game but may not be powerful enough for more complicated games and meshes.

The thing is though that ai is a hard core difficult topic and if there is not someone actively maintaining the repo, things will get stale real quick. I am always open to new libraries so if you run across one thats useable in jme and actively maintained, then let us know cause I am confident others would like to check it out also.

That warning is also possibly a jme-ai specific thing because I found nothing like it in recast, which that library is based off of. It may exist in recast and I missed it but I have never seen anything like it myself.

No matter what you do though, its a PITA and alot of learning is required.


I went through the same thing in Blender myself. Ignore it if it isn’t affecting anything. Which I found to be the case. I never found out where those pointing down normals were causing a problem myself and was able to move across the triangles in question.

1 Like

recast for j is so big, I can’t read all of that project, is not there any recast for JME implementation?

You can try mefisto wrapper for recast4j.

You will find the links to it here.

I wrote a wiki for the demo at the demo website but you must understand that the demo has all the proper classes implemented to make the wrapper work in a game and just trying to use jme-recast4j will not work like the demo does without them.

You have to read all my posts and fully implement all those extra classes.

On the bright side, this example file contains every build type there is for procedural builds of recast4j,
https://github.com/MeFisto94/jme3-recast4j-demo/blob/52af8a0e1a9b26f03f326a9df8d3dd773a686f25/src/main/java/com/jme3/recast4j/demo/states/NavState.java as well as pathfinding for individual characters.

Those classes are in this folder of the repo.

The DemoApplication.java file there is the only file that is specific to the demo itself. The rest are files that you will need in addition to the wrapper.

These files JmeInputGeomProvider, GeometryProviderBuilder2, RecastBuilder would allow you to probably exclude the wrapper library altogether and use recast4j instead. But that requires knowledge of recast4j and the wrapper to pull it off.

The thing about recast4j is it is only intended to be a java wrapper of the original recast project. As such, piotr only ported it up to that point where the project was abandoned. Recast was never intended to be used as anything more than a demo really so my work completes some of those generic features, allowing it to be used in jme proceduraly.

Ai is hard stuff. People get paid big money to do it. Its a field all in and of itself. You wont get what you want without alot of study and effort. There is no easy way I found.

Thats why I would love to find a solution thats like the holy grail of ai, just not seen anything to date like that.

I have spent a huge amount of time on it myself, maybe about 12 months in total, and would consider myself intermediate at best in using recast. Its one of those things that the more you use it the more you learn.

So, if you happen run across something easier, that is full featured and is maintained, let me know because it sure would be appreciated immensely.

1 Like

Forgot to mention, the wiki I wrote also tells you how to use the demo and the demo has an extensive set of help files that explain every setting of recast crowd. The demo allows you to try out all kinds of parameters and pathfinding filters for crowd.

There are two test areas that have different things like doors or water that can be activated or deactivated by uncommenting

and comment out.

That will show you how doors work in recast and how water works. Its a shame this was never finished. No time for it now myself.

1 Like

is it working? something like this is possible in that lib?
1.loading a NavMesh into jme and get the Mesh data.
2. pass mesh data to jme3-recast4j lib and get instance for pathfinding.
3.use it to find a path as a wayPoint list.
4.what about Thread safety? is it working thread-safe? for batch moving character about 40 pathfinding call at the same time…

5- what is recast crowd for? is it using for pathfinding to moving a batch of characters at the same time?

1-3 yes
4 No issues. Can move hundreds of characters at a time, as a crowd or individually.
5. Crowd is just that. You have a group of characters that move in unison to a target. Honoring physics and any path restrictions while doing so, like if to fat to move through a door, they dont go through.

There are issues though.

The similarities with jme-ai are that it uses many of the same techniques to accomplish navmesh generation, but coded cleaner. If you understand jme-ai you could easily pull what you want from it and write your own wrapper. Then you may even avoid some of the issues jme-recast4j has or figure out the issues entirely.

1 Like

thank you so much.

in this section, what is the query?

The object you are using to query a navigation mesh for pathfinding.

1 Like

is there any difference between using the test.md file and test.nm?
the second one must be faster, am I right?

sorry, this part was because of my wrong printing position code:
I tested it, but why it returns 4 position or 2 waypoints for straight pathfinding?
I mean if the way is a line so need just 2 vector3f for start and end position of a line, not 2 waypoints.
soeme thing like this:
waypoints size is :2
point0 is :[(0.0, 0.1, 0.0), (1.0, 0.1, 1.0)]
point1 is :[(0.0, 0.1, 0.0), (1.0, 0.1, 1.0)]

A (nm) is a complete navmesh with meshData and tiles. A (md) is the mesh data for a tile.

A solo navmesh is actually one big tile with one MeshData (md) so you can save just the data and build the navmesh from that. If you have tiles, you have MeshData for each tile so use MeshSetWriter, which will save every tile with its MeshData. You can use MeshSetWriter for every mesh, solo or tiled.

You get NO benefit from one large mesh. Solo navmesh was a restriction of the first release of the recast code. It was later replaced by Tiled meshes and solo mesh was kept for backward compatibility reasons.

This is an example of how to save, load and display a tiled mesh for debugging.

Every possible means of saving and loading the mesh is covered in the NavState file. Its is a must read if you are going to use this. I wrote a ton of comments giving as much detail as I could on things.

This is an explaination of saving and loading.

As you can see, with one you build a NavMesh

    //Read in saved MeshData and build new NavMesh.
    MeshDataReader mdr = new MeshDataReader();
    MeshData read = mdr.read(new FileInputStream("test.md"), 3);
    NavMesh navMeshFromData = new NavMesh(read, 3, 0);

where the other is a NavMesh.

    //Or read in saved NavMesh.
    MeshSetReader msr = new MeshSetReader();
    NavMesh navMeshFromSaved = msr.read(new FileInputStream("myNavMesh.nm"), 3);
1 Like

I updated that wiki to show query object.


1 Like

also, I can’t find out what is the 'extents' for?

//Extents can be anything you determine is appropriate.
float[] extents = new float[] { 2f, 4f, 2f };

The search distance along each axis. [(x, y, z)]

1 Like

is it using to find the nearest traversable point to the endpoint, if the endpoint is not traversable?

@mitm please answer this question, I really need to know and use it.

You should be able to read the source?

1 Like

Or even read the wiki I wrote?

For path finding, you will need to know the first and last polygons and a point inside those polygons that will constitute the start and end position for your path. The findNearestPoly() method returns references and points where references are polygons, and points are Vectors inside the polygon. The findNearestPoly() method will find the closest polygon to a point, using the given extent and the supplied filter.

If the point supplied by you is inside the found polygon, that point will be returned, otherwise, findNearestPoly() will constrain the point to the polygon found, assuming one is found. If the search does not intersect any polygons, the search getNearestRef() will be zero. You should always check for this prior to calling getNearestPos() .

An example of something that could return zero would be supplying a point that is not part of the NavMesh like walls or objects that are to far outside the extents of the search, or if all polygons are filtered out.

Of course this all depends on what you filter also.

1 Like