AI Libraries for Panda3D

That’s a shame, but I fully understand the situation. And I will definitely make use of the rest of PandaAI. Thanks.

Good News!!!

We are excited to say that the PandAI pathfinding solution now supports Blender. We have created a separate mesh generation tool for creating a navigation grid from a plane made using Blender. You can download the required files from here:

www.srinavinnair.com/downloads/BlenderMeshGen.zip

In the above zip file you will find the following:

  1. A ReadMe file which explains how to use the tool.
  2. The python script required to generate navmesh.csv from Blender full and collision planes.
  3. Sample planes created in Blender which were used for testing.

A few IMPORTANT things:

a. Make sure your the full and collision planes that you make are on the ‘X - Z plane’ of Blender.
b. This is for planes created using ONLY Blender. For Max and Maya please continue to use our previous meshgen tool.

Here is a video of pathfinding working with planes created in Blender:

youtube.com/watch?v=M72PcdYvbVE

NOTE: The lag is due to a lot of spheres being rendered as nodes.

Lastly, it would be really helpful if people using PandAI and Blender could give us feedback about this new tool we have provided. If you come across any bugs or discrepancies please report it in this thread.

Thanks a lot for your support!

  • Team PandAI.

You guys are just fantastic. I have downloaded already and I will test it and give feedback as soon as I can. This is really great news.

Thanks very much for all your hard work.

Thanks a lot.

We are glad that you can still use it.

This looks like it will be very useful in my current project; I’m trying to build an RTS game, and hope to use PandAI for navigation, since it’s far more practical than writing my own algorithms.

I am a little confused as to how to use the Navigation Mesh Generator Tool for Blender, however. It says in the instructions to use two arguments, a plane file and a plan collision file. At the moment, I have my visible geometry and my collision geometry in the same .egg file, on different layers. Does this mean I have to make a separate file with collision geometry? And if so, what is the geometry I need to pass - all collision geometry, i.e. floors, walls, and everything else?

Also, it may be related to me misusing the mesh generator, but when I try to run it the meshgen crashes, either at step 2 or step 3 (creating notes on the mesh, or identifying neighbour nodes for each node on the mesh). I get no error message in the console, just a windows pop-up telling me that meshgen.exe is no longer working and needs to be shut down.

Thanks a lot for this work, by the way - I’m sure it will save a lot of people a lot of trouble! I look forward to incorporating PandAI into my game.

@ GarrickW

I would suggest the best way to test it out is to create a simple 5x5 plane in Blender in the x-z axis. (By 5x5 I mean use subdivisions)

This will be your full_mesh.egg.

Now remove a couple of faces from the plane and export another egg as the coll_mesh.egg.

See if you can use the mesh generator on this to get a navmesh.csv.

Use this nevmesh.csv in PandAI pathfinding and see if you can get an AI character to pathfind to another.

  • Note :
    If A and B are AI characters and A is to pathfind to B, make sure the starting positions of A and B should be on the faces which can be traversed.

Thanks for the quick reply! I’ve gone ahead and done as you suggested, and made a very simply mesh; the mesh generation, at least, was successful and without error, which is more than can be said for my custom map (which is now consistently crashing at Stage 3). I’m setting it up to test for pathfinding now, but something has occured to me. All the videos on the PandAI website that I watched showed totally flat 2D spaces being navigated. My custom mesh, however, has some inclinations that are meant to be navigable by the units using pathfinding, so the floor mesh - and thus presumably the navigation mesh - have to be three dimensional.

Might this be an issue? I know someone asked this about 7 months, but I figure things may have changed since then. It’s one of the few seemingly relevant differences that I can think of between a simple plane and my mesh (otherwise the mesh is larger, has materials, and uses a “Polyset keep descend” collision tag).

Thanks for taking the time to reply!

EDIT: Ah, I’ve solved the problem. After writing this post, I figured it would be best to check everything, just in case, so I went and deleted the collision tags and the materials in Blender, and tried again. This time, it worked, 3D inclinations and all! Between the materials and the collision tags, I imagine it was the tags that were messing the meshgen up, though I can’t be sure. Now to give PandAI a spin. :wink:

EDIT 4: So I now have the “couldnt find source” “couldnt find destination” error, and I can’t seem to get past it. I’ve done what another user earlier in this thread did, and checked to make sure all values were on the proper axis, but this didn’t help. I’ve made the meshes on the X-Y axis and the X-Z axis, as well as manually flipping the values in the .CSV file, but the AI can’t find its source or its destination.

I’ve also flattened the meshes, to deal with the fact that PandAI is 2D, but the flattened meshes won’t generate a navmesh anymore, though I did nothing to them besides set their Z-scale to 0. I’ve also left them their height - and I’ve manually set height, PosZ, or both to 0 in the .CSV file. The only meshes that have successfully been made into a navmesh are the 3D ones I tried, though, and that one continues to return “couldnt find destination” and “couldnt find source”.

EDIT 5: I am starting to wonder, after looking at the .CSV file, whether the problem isn’t something else. One major problem I can see is that my model has setScale(10). For some reason, I am unable to replicate functionning full and collisionmeshes anymore, so I am stuck with the ones that are 10x smaller than the map.

I have tried sizing the environment and actors down to scale(1), but this makes my game go wonky, with units jittery against the floor, falling through, or not falling at all and floating around in space, not to mention somehow disabling my selection methods.

Another issue is that, in the CSV file, all values, X and Y, are positive. This is strange, since I when exported the meshes, they were centered on 0, 0, 0, and there were vertices in every quadtrant. In any case, this is probably also a problem, given that my environment is centered on the origin.

I must see if I can correct all these issues; hopefully I’ll manage something soon! If I do, I’ll be sure to post whatever the solution is, in case others ever have difficulty.

EDIT 6: I’m not sure what I did; I created a second version of the terrain, and in that deleted absolutely everything (including light, camera, materials and vertex groups) except the full terrain, enlarged it 10 times, flattened it, and exported it. I forgot to remove the collision tags, but meshGen thought the eggs tasted good, so it seems those aren’t important.

However, I’m not out of the water yet. I find the game no longer gives me the “couldnt find” error if I leave the CSV be, but then I discover that the CSV contains a posZ value of -0,0478745 for all existing nodes, even though I’ve made absolutely certain that the meshes are all at exactly Z:0.

In addition, the CSV file is not easily readable in Excel, so I divide the data into columns, such that I can more easily set all the posZ values to 0 - and when I save with columns, the errors return, even if I leave the data otherwise untouched. I am unsure as to how to put everything back into a single column once I’ve changed the data, all while preserving the commas.

At least this is progress; the meshes, it would appear, work!

Before I get into your problem, I would like you to try this out:

  1. Did you get path finding working on a simple 2d mesh ?

If not thats the first thing you need to do to understand the process and only then proceed to complex meshes.

  1. Have a look at the roaming ralph tutorial on the PandAI download.

This tutorial shows how you can use the path finding to navigate your player on uneven terrain.

Once you do this, please post back and we can proceed.

  • Note: Modifying the navmesh.csv is not recommended unless you understand exactly what each field means. I would say it is better to get the egg format right so that the mesh gen creates the correct navmesh than to manually change it.

[EDIT]
Try to think of the navigation mesh as seperate from the terrain. The navigation mesh should be thought of as the underlying logic for where a character can move. The terrain can be thought of as the graphics over it such that it doesn’t look like a simple plane with subdivisions :slight_smile:

So I did as you said, and tried a simpler grid with full pathfinding, shaving all the useless code away so that only the grid, the actor and the move controls remained.

Until then I had only got the grid to generate a proper mesh, and thought that was enough, but apparently it wasn’t. I continue to have the same problem (no console errors, but no pathfinding either), which I imagine means I’ve not yet understood some of the basics. I’m really sorry to bother you with my inexperience, and I’m very grateful you’re taking the time to help! I’ve tried to isolate the problem, and here’s what I know about the situation:

  • The grid, and full mesh used to generate the navmesh, is regular, 6x6 square-shaped quads; the collision mesh is the same, but with four quads removed from the center

  • Movement using means other than pathfinding work well on the simple grid; switching to the pathfinding system requires only commenting one line and uncommenting another.

  • Collision with the floor appears to be functionning well.

  • I have it set up such that the game displays the coordinates being passed to .pathFindTo(), and I have checked these coordinates in the navmesh.csv; the coordinates passed are within the range covered by the navmesh (in a square of roughly -50 to 50 in both the X and the Y).

  • Just to be certain, I tried to code the actor into pathfinding to one of the exact locations in the navmesh, (-25.15, -41.9166, 0), in case my commands were falling through the cracks, but the actor was still unresponsive.

  • Neither the grid nor the navmesh.csv contain height (all Z:0), and I am passing coordinates with a Z of 0 to .pathFindTo().

  • I have tried using the .seek() function instead of pathFindTo(), and this was equally unresponsive (which leads me to believe I made a rather fundamental error)

  • I have created an AI world, and am updating the AI world with a continuous task (I’ve done this within the main class, the actor class, and both).

  • The visible grid and the collision grid are identical to the one used as full mesh (the col mesh has 4 quad faces removed from the center).

  • I have set up the actor’s AI using this code (admittedly, I am not sure what values of mass, force and maximum force are appropriate, but I have tried reducing one or the other, to no effect). Note that ‘world’ is the main class, also the one that creates self.actor, and self.actor is an Actor() with animations:

        self.actorAI = AICharacter("PacManAI", self.actor, 20, 20, 60)
        world.aiWorld.addAiChar(self.actorAI)
        self.actorBehaviors = self.actorAI.getAiBehaviors()
        self.actorBehaviors.initPathFind("navmesh.csv")

Again, thank you for taking the time to help me out!

When you say no pathfinding, could you elaborate please.

Is there no movement at all ?

Where in your code is the ai world update task set ? Try to start the task after initPathfind and see if it solves anything.

Was there no error in the console at all ?

Try to use pathFindTo(some position vector) and see if that works.

I did this, and suddenly there was movement! (the actor had been doing nothing at all). It appears I had set the task along with a couple of other tasks, and added the AI code in after them. When I switched it around, there was movement and seeking. Now the actor responds to the .seek() function perfectly well on the test grid, though on my own map it tends to overshoot the target and then get stuck colliding with walls.

However, it now does the most peculiar thing with .pathFindTo(): if there is a big difference in the Y coordinate (the X is unaffected), the actor traces what I can only describe as a function looking something like what you get if you were to graph a function like (x^(x / 12) * sin(5x)) - in other words, the actor swoops far beyond the target’s X coordinate, and then back towards its original X (but not quite there), and back again to the target’s, and again towards it’s original X, each time staying closer and closer to the target’s X coordinate unti it reaches the target (passing over holes in the collision mesh as it does so). If the distance is long enough, it begins to go out further and further from the target’s X again before reaching the targed, like the function is growing again. This behavior isn’t present when the distance is mostly along the X axis.

But now it’s working, on some level, and I am going to go back through my code to see if I’m not accidentally causing this behavior. Thanks a million for the assistance! :smiley:

Sure no problem :slight_smile:

I still recommend that when you are testing something like this in your game, first always do some unit testing on it.

So in this case, you should try to have a scene with an actor, a path finding mesh and a destination actor.

See if the path finding works for this simple environment.

If so then translate this into your game. This way you know that it isn’t something wrong with the path finding if it breaks. This will also save you a lot of debugging headaches :slight_smile:

Please post back here if you have any more queries.

Cheers.

[EDIT]

If you could replicate a simple behavior such as this video we made using a Blender mesh:

youtube.com/watch?v=M72PcdYvbVE

with your simple mesh, then you are well on your way :slight_smile:

It looks like you are using meshgen.exe. For Blender, we have created another meshgen tool. Are you using that or have you been testing with meshgen.exe?

Well, I was under the firm impression I had downloaded and used the blender tool, but since you mentionned it, I went and checked, and it turns out that I had downloaded it, but that I already had the meshgen.exe, and had been mistakenly using that. Now I really feel like a noob. Thanks for the heads-up, though! It’s great that Panda3D has such helpful community members. Hopefully this will solve the other problems I’ve been having; I’ll edit the post once I’ve given it a shot.

Sweet! I think you should be able to get it to work now. Just make sure you create the planes in x-z in Blender and the scales of the planes shouldn’t be changed in the game. And as NNair had mentioned begin with a simple mesh, once you have that working you should be set for complex meshes.

We will be moving the Blender meshgen tool to our official website soon. Until then you can get it from here,

www.srinavinnair.com/downloads/BlenderMeshGen.zip

We apologize for any confusion this may have caused.

Let us know if it works.

Thank you!

Hm, well it’s not quite working the way I planned. I’m trying this with a simple grid, 10 x 10, made in the X-Z axis, and while the egg-trans command seems to work find, using BlenderMeshGen.py returns the following error each time:

Assertion failed: index >= 0 && index < (int)size() at line 467 of c:\panda3d-1.
7.0\panda\src\egg\eggPrimitive.I
Traceback (most recent call last):
  File "BlenderMeshGen.py", line 297, in <module>
    app = MyApp()
  File "BlenderMeshGen.py", line 47, in __init__
    self.iterateEggPoly(self.egg, "Full")
  File "BlenderMeshGen.py", line 94, in iterateEggPoly
    self.iterateEggPoly(child, type)
  File "BlenderMeshGen.py", line 94, in iterateEggPoly
    self.iterateEggPoly(child, type)
  File "BlenderMeshGen.py", line 71, in iterateEggPoly
    egg.getVertex(2), egg.getVertex(3))
AssertionError: index >= 0 && index < (int)size() at line 467 of c:\panda3d-1.7.
0\panda\src\egg\eggPrimitive.I

I’ve tried making the grids both Y-up and Y-down, but the same thing happens. I also tried making a navmesh out of .egg files I hadn’t yet transformed using egg-trans, and got this error instead:

Traceback (most recent call last):
  File "BlenderMeshGen.py", line 297, in <module>
    app = MyApp()
  File "BlenderMeshGen.py", line 50, in __init__
    self.createNewFullList()
  File "BlenderMeshGen.py", line 110, in createNewFullList
    if currentColNode.vertex[self.rightVertex] == self.oldList[i].vertex[self.lo
westVertex] and currentColNode.vertex[self.toprightVertex] == self.oldList[i].ve
rtex[self.topVertex]:
AttributeError: MyApp instance has no attribute 'rightVertex'

The grids are very simple, no modifiers and nothing special; the fullmesh is a complete grid, and the colmesh is the same complete grid (duplicated) with several faces deleted. Both are the same size, and are centered on the origin. I’ve tried using the .eggs that “worked” with meshgen, and those don’t pass either.

I took a look at your .BLEND files included with the BlenderMeshGen, and I noticed you had deleted only faces, leaving the vertices between the empty spaces, so I tried that, and I still got the first error detailed above.

I tried using the egg files you included to make a mesh, just to be safe, and they worked fine, so the problem would seem to be with my models. However, I can’t spot the difference, besides the basic layout. I noticed some of the faces in your blender models were selected; that wouldn’t have an influence, would it? Otherwise, I saw no special tags or toggles, though admittedly I’m somewhat new to Blender, too, and so I probably didn’t look everywhere. In case it matters, I am using Blender 2.49b, and Panda3D 1.7.0.

By the time I get this all working, there will be a great bunch of help in this thread for anyone else who has similar problems! Thanks again for the help!

Thanks for giving all the details of your problem. Okay so like you said, I feel the root of the problem is how these planes are being created in Blender. Could you provide us a step by step procedure of how you created the full and coll planes in Blender?

EDIT: Also how you spit out the eggs.

Absolutely. Here’s what I did:

  1. Open blender, and delete the starting cube.

  2. Create a grid using W -> Mesh -> Grid, and set its values to 10, instead of the default 32. Open Transform Properties to keep an eye on the various values.

  3. Scale 200x, such that the X and Y dimensions in Transform Properties read 400.000 (this is the size of the terrain model I am using).

  4. While selecting the grid, press M and have the grid appear on Layers 1 & 2.

  5. Switch to Layer 2, and Duplicate the grid, moving it to the side to keep it visually separate. Set the duplicate to only appear in Layer 2, and the original to only appear in Layer 1.

  6. Set the coordinates of the dupliacte, via Transform Properties, to 0, 0, 0.

  7. Rename the original “fullmesh”, and the duplicate “colmesh”.

  8. Switch to “colmesh,” and open Edit mode. Press A to deselect everything.

  9. Select the faces as in this sketch, where the Xs are selected (the grid has 9x9 faces):


–xxxxx–
–xxxxx–
–xx-xx–
–x--xx–
----xxx–
—xxxx–


  1. Press Del, then select Only Faces.

  2. Back in Object Mode, set the X-rotation via Transform Properties to -90, such that the direction in which the Y-axis grows is “up” (I also previously tried +90, but this didn’t help).

  3. Switch over to “fullmesh,” and again, switch the X-rotation to -90.

  4. Open the Outliner in a side screen, such that I know what I’m selecting. Then, in Layer 1, select the fullmesh, make sure it’s the only thing selected, and select File -> Export -> Chicken R91(.egg). Set name to “testmesh.egg” and export.

  5. Deselect “fullmesh”, switch to Layer 2, and select “colmesh”; rename the file in the Chicken screen to “testcolmesh.egg”, and export.

  6. Cut “testmesh.egg” and “testcolmesh.egg” from their directory, and past them into the directory where BlenderMeshGen.py is located.

  7. In the command prompt, in the directory where the files are now at, type:

egg-trans -C -o testmesh.egg testmesh.egg

The result looks like this:

Triangulating polygons.
  (81 triangles produced.)
Writing testmesh.egg
  1. Repeat the same, replacing “testmesh.egg” with “testcolmesh.egg”. The result is:
Triangulating polygons.
  (81 triangles produced.)
Writing testcolmesh.egg
  1. Still in the command prompt, enter:
python BlenderMeshGen.py testmesh.egg testcolmesh.egg

The result is this, including the error:

DirectStart: Starting the game.
Known pipe types:
  wglGraphicsPipe
(all display modules loaded.)
Creating full node list...
Assertion failed: index >= 0 && index < (int)size() at line 467 of c:\panda3d-1.
7.0\panda\src\egg\eggPrimitive.I
Traceback (most recent call last):
  File "BlenderMeshGen.py", line 297, in <module>
    app = MyApp()
  File "BlenderMeshGen.py", line 47, in __init__
    self.iterateEggPoly(self.egg, "Full")
  File "BlenderMeshGen.py", line 94, in iterateEggPoly
    self.iterateEggPoly(child, type)
  File "BlenderMeshGen.py", line 94, in iterateEggPoly
    self.iterateEggPoly(child, type)
  File "BlenderMeshGen.py", line 71, in iterateEggPoly
    egg.getVertex(2), egg.getVertex(3))
AssertionError: index >= 0 && index < (int)size() at line 467 of c:\panda3d-1.7.
0\panda\src\egg\eggPrimitive.I

Might it possibly be the fact that I am using layers?

As a side note, my claiming that the navmesh from your own egg files worked seems to have been premature. I saw it getting along further than my own had, and figured it would work, so I let it be; but I realised about 30 minutes later that it was still at “write to csv file”, and was displaying a grey Panda screen. I terminated it, figuring it wouldn’t go any further. I am starting it up again now, to see what happens this time.

I know whats going wrong.

Try doing all those steps without the eggtrans for any of the eggs

Eggtrans was a step we needed for the old meshgen.

This new meshgen uses quads and so triangulation is not needed.

Please test this out.

And adding to that, try NOT to use layers for now. Follow these simple steps:

  1. Create the grid at origin.
  2. Rotate to x-z plane.
  3. Scale to whatever size you need. (Do a uniform scale for now).
  4. Save as full mesh and egg it.
  5. Select faces you want to delete and delete them.
  6. Save as coll mesh and egg it.
  7. Now directly use the egg files with the python meshgen tool for Blender.
  8. Use the navmesh.csv that is generated with your game.

Let us know if the solution we provided work for you. Thanks!