AI Libraries for Panda3D

Ok so I would like to announce that the first version of the code to produce a navmesh.csv has been successful. This system was setup for use with geomipterrain. I am now able to pathfind perfectly with this code.

How it works: I used the code to setup a geomipterrain and then grab a bunch of information from the terrain then math code is looped through and a set of points are created that represent the grid that will be used to setup the paths. This does include finding all the neighboring grid squares in the correct order. as it is going throught the lines of the code it is writing them to navmesh.csv now you have the file you need to use PandaAI without having to recreate your terrain in maya or Max.

This system could be rewritten to use any type of terrain the only limit ive found so far is the number of lines in excel. This means that larger terrains Like geomip or |Craigs| new paging terrain may have issues if you make them too big as you would need lots of decent size squares to fill the terrain. (This system could be changed to paging as well if the code runs fast enough)
also depending on the version of excel used this may limit you to 65k lines (office 2003: around 75 squares per row so terrain smaller than 700px X 700px).

To find out the number of excel rows needed before you try to make the file use (N*N)*9 where N is number of sqaures requested. to find a good number for squares you may need to test although i find using the length of my picture/9 shows me aprox the number of squares i want as i find 9px per square is pretty accurate.

I plan on releasing the code later today once optimizing the code is completed.

I would like to take the time to thank a few people that made this possible:
JohnKol (for giving me the info for setting up the navmesh)
|Craig| (For walking me through optimizing the code)
CMU (For making the PandaAI)

Also thank you to everyone in IRC chat that let me bounce ideas off you for this as it was a big help in figuring out how to write the code.
Edit: This code has been fixed for issues that were found below this post.

import direct.directbase.DirectStart
from direct.showbase.DirectObject import DirectObject
from panda3d.core import PNMImageHeader, Vec3, Texture, GeoMipTerrain, VBase4
from panda3d.core import Filename, BitMask32, TextureStage
#import csv
class World(DirectObject):
    def __init__(self):
        """
        This is a simple system to make PandaAI work with Geomip terrain
        Use ctrl-F to find the line you need to change by using the code inserted at the number in this text
        Things you need to change to make this work:
        1.use your heightmap                            - self.terrain.setHeightfield(Filename("Terrain/Level 1/terraintest.bmp"))
        2.change to number of blocks you want to use    - self.terrain.setBlockSize(64)
        3.Change your texture                           - loader.loadTexture('Terrain/Level 1/ground.jpg')
        4.change this to your heightmap again           - header.readHeader(Filename("Terrain/Level 1/terraintest.bmp"))
        
        Now you can use this code to make your Navmesh.csv for PandaAI.
        """
        base.cam.setPos(-100,512,3000)
        base.cam.lookAt(512,512,0)
        #Load the first environment model
        self.terrain = GeoMipTerrain("ground")
        self.terrain.setHeightfield(Filename("Terrain/Level 1/terraintest.bmp")) #Terrain/game heightmap.bmp
        # Set terrain properties
        self.terrain.setBlockSize(256)
        self.terrain.getRoot().reparentTo(render)
        self.terrain_tex = loader.loadTexture('Terrain/Level 1/ground.jpg')
        self.terrain_tex.setMagfilter (Texture.FTLinear) 
        self.terrain_tex.setMinfilter(Texture.FTLinearMipmapLinear)

        # Store root NodePath for convenience then set root settings for the terrain
        root = self.terrain.getRoot()
        #Set the terrain itself to be collide-able.
        root.setCollideMask(BitMask32.bit(0))
        root.reparentTo(render)
        ts = TextureStage('ts')
        root.setPos(0,0,0)
        root.setSz(50)
        root.setTexScale(ts.getDefault(),15,15)
        root.setTexture(self.terrain_tex,1)
        root.setTwoSided(True)
        
        header = PNMImageHeader()
        header.readHeader(Filename("Terrain/Level 1/terraintest.bmp"))
        hy = header.getYSize()
        hx = header.getXSize()
        bs = self.terrain.getBlockSize()
        cuber = (hx-1)/bs
        cubing2 = ((hx-1)/bs)/2

        file=open("navmesh.csv", "w")
        def doLine(*x): file.write(','.join( str(v) for v in x)+'\n')
        
        doLine("Grid Size",bs)
                
        doLine("NULL","NodeType","GridX","GridY","Length","Width","Height","PosX","PosY","PosZ")
        
        for j in range(bs):
            cubing = ((hx-1)/bs)/2
            for i in range(bs):
                
                def h(f,a,b,c=1):
                    if f: doLine(1,1,0,0,0,0,0,0,0,0)
                    else: doLine(0,c,i+a,j+b,cuber,cuber,0,cubing+cuber*a,cubing2+cuber*b,self.terrain.getElevation(cubing+cuber*a,cubing2+cuber*b)*self.terrain.getRoot().getSz())
                
                h(False,                   0, 0,c=0)
                h(i-1 < 0 or j+1 > bs-1,  -1, 1)
                h(i-1 < 0,                -1, 0)
                h(i-1 < 0 or j-1 < 0,     -1,-1)
                h(j-1 < 0,                 0,-1)
                
                h(i+1 > bs-1 or j-1 < 0,   1,-1)
                h(i+1 > bs-1,              1, 0)
                h(i+1 > bs-1 or j+1 >bs-1, 1, 1)
                h(j+1 > bs-1,              0, 1)
                
                cubing += cuber
            cubing2 = cubing2 + cuber
                 
        #Updates the taskMgr
        taskMgr.add(self.updateTask, "update")

        #this updates the terrain when needed
    def updateTask(self, task): 
        self.terrain.update()
        self.terrain.getRoot().setCollideMask(BitMask32.bit(0)) 
        return task.cont 

w=World()
run()