Blender V2.61 - r43446

KX_NavMeshObject.cpp

Go to the documentation of this file.
00001 /*
00002  * ***** BEGIN GPL LICENSE BLOCK *****
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License
00006  * as published by the Free Software Foundation; either version 2
00007  * of the License, or (at your option) any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012  * GNU General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software Foundation,
00016  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00017  *
00018  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00019  * All rights reserved.
00020  *
00021  * The Original Code is: all of this file.
00022  *
00023  * Contributor(s): none yet.
00024  *
00025  * ***** END GPL LICENSE BLOCK *****
00026  */
00027 
00028 #include "MEM_guardedalloc.h"
00029 
00030 #include "BLI_math_vector.h"
00031 #include "KX_NavMeshObject.h"
00032 #include "RAS_MeshObject.h"
00033 
00034 #include "DNA_mesh_types.h"
00035 #include "DNA_meshdata_types.h"
00036 
00037 extern "C" {
00038 #include "BKE_scene.h"
00039 #include "BKE_customdata.h"
00040 #include "BKE_cdderivedmesh.h"
00041 #include "BKE_DerivedMesh.h"
00042 #include "BKE_navmesh_conversion.h"
00043 }
00044 
00045 #include "KX_PythonInit.h"
00046 #include "KX_PyMath.h"
00047 #include "Value.h"
00048 #include "Recast.h"
00049 #include "DetourStatNavMeshBuilder.h"
00050 #include "KX_ObstacleSimulation.h"
00051 
00052 static const int MAX_PATH_LEN = 256;
00053 static const float polyPickExt[3] = {2, 4, 2};
00054 
00055 static void calcMeshBounds(const float* vert, int nverts, float* bmin, float* bmax)
00056 {
00057     bmin[0] = bmax[0] = vert[0];
00058     bmin[1] = bmax[1] = vert[1];
00059     bmin[2] = bmax[2] = vert[2];
00060     for (int i=1; i<nverts; i++)
00061     {
00062         if (bmin[0]>vert[3*i+0]) bmin[0] = vert[3*i+0];
00063         if (bmin[1]>vert[3*i+1]) bmin[1] = vert[3*i+1];
00064         if (bmin[2]>vert[3*i+2]) bmin[2] = vert[3*i+2];
00065 
00066         if (bmax[0]<vert[3*i+0]) bmax[0] = vert[3*i+0];
00067         if (bmax[1]<vert[3*i+1]) bmax[1] = vert[3*i+1];
00068         if (bmax[2]<vert[3*i+2]) bmax[2] = vert[3*i+2];
00069     }
00070 }
00071 
00072 inline void flipAxes(float* vec)
00073 {
00074     std::swap(vec[1],vec[2]);
00075 }
00076 KX_NavMeshObject::KX_NavMeshObject(void* sgReplicationInfo, SG_Callbacks callbacks)
00077 :   KX_GameObject(sgReplicationInfo, callbacks)
00078 ,   m_navMesh(NULL)
00079 {
00080     
00081 }
00082 
00083 KX_NavMeshObject::~KX_NavMeshObject()
00084 {
00085     if (m_navMesh)
00086         delete m_navMesh;
00087 }
00088 
00089 CValue* KX_NavMeshObject::GetReplica()
00090 {
00091     KX_NavMeshObject* replica = new KX_NavMeshObject(*this);
00092     replica->ProcessReplica();
00093     return replica;
00094 }
00095 
00096 void KX_NavMeshObject::ProcessReplica()
00097 {
00098     KX_GameObject::ProcessReplica();
00099 
00100     BuildNavMesh();
00101     KX_Scene* scene = KX_GetActiveScene();
00102     KX_ObstacleSimulation* obssimulation = scene->GetObstacleSimulation();
00103     if (obssimulation)
00104         obssimulation->AddObstaclesForNavMesh(this);
00105 
00106 }
00107 
00108 bool KX_NavMeshObject::BuildVertIndArrays(float *&vertices, int& nverts,
00109                                        unsigned short* &polys, int& npolys, unsigned short *&dmeshes,
00110                                        float *&dvertices, int &ndvertsuniq, unsigned short *&dtris, 
00111                                        int& ndtris, int &vertsPerPoly)
00112 {
00113     DerivedMesh* dm = mesh_create_derived_no_virtual(KX_GetActiveScene()->GetBlenderScene(), GetBlenderObject(), 
00114                                                     NULL, CD_MASK_MESH);
00115     int* recastData = (int*) dm->getFaceDataArray(dm, CD_RECAST);
00116     if (recastData)
00117     {
00118         int *dtrisToPolysMap=NULL, *dtrisToTrisMap=NULL, *trisToFacesMap=NULL;
00119         int nAllVerts = 0;
00120         float *allVerts = NULL;
00121         buildNavMeshDataByDerivedMesh(dm, &vertsPerPoly, &nAllVerts, &allVerts, &ndtris, &dtris,
00122             &npolys, &dmeshes, &polys, &dtrisToPolysMap, &dtrisToTrisMap, &trisToFacesMap);
00123 
00124         MEM_freeN(dtrisToPolysMap);
00125         MEM_freeN(dtrisToTrisMap);
00126         MEM_freeN(trisToFacesMap);
00127 
00128         unsigned short *verticesMap = new unsigned short[nAllVerts];
00129         memset(verticesMap, 0xffff, sizeof(unsigned short)*nAllVerts);
00130         int curIdx = 0;
00131         //vertices - mesh verts
00132         //iterate over all polys and create map for their vertices first...
00133         for (int polyidx=0; polyidx<npolys; polyidx++)
00134         {
00135             unsigned short* poly = &polys[polyidx*vertsPerPoly*2];
00136             for (int i=0; i<vertsPerPoly; i++)
00137             {
00138                 unsigned short idx = poly[i];
00139                 if (idx==0xffff)
00140                     break;
00141                 if (verticesMap[idx]==0xffff)
00142                 {
00143                     verticesMap[idx] = curIdx++;
00144                 }
00145                 poly[i] = verticesMap[idx];
00146             }
00147         }
00148         nverts = curIdx;
00149         //...then iterate over detailed meshes
00150         //transform indices to local ones (for each navigation polygon)
00151         for (int polyidx=0; polyidx<npolys; polyidx++)
00152         {
00153             unsigned short *poly = &polys[polyidx*vertsPerPoly*2];
00154             int nv = polyNumVerts(poly, vertsPerPoly);
00155             unsigned short *dmesh = &dmeshes[4*polyidx];
00156             unsigned short tribase = dmesh[2];
00157             unsigned short trinum = dmesh[3];
00158             unsigned short vbase = curIdx;
00159             for (int j=0; j<trinum; j++)
00160             {
00161                 unsigned short* dtri = &dtris[(tribase+j)*3*2];
00162                 for (int k=0; k<3; k++)
00163                 {
00164                     int newVertexIdx = verticesMap[dtri[k]];
00165                     if (newVertexIdx==0xffff)
00166                     {
00167                         newVertexIdx = curIdx++;
00168                         verticesMap[dtri[k]] = newVertexIdx;
00169                     }
00170 
00171                     if (newVertexIdx<nverts)
00172                     {
00173                         //it's polygon vertex ("shared")
00174                         int idxInPoly = polyFindVertex(poly, vertsPerPoly, newVertexIdx);
00175                         if (idxInPoly==-1)
00176                         {
00177                             printf("Building NavMeshObject: Error! Can't find vertex in polygon\n");
00178                             return false;
00179                         }
00180                         dtri[k] = idxInPoly;
00181                     }
00182                     else
00183                     {
00184                         dtri[k] = newVertexIdx - vbase + nv;
00185                     }
00186                 }
00187             }
00188             dmesh[0] = vbase-nverts; //verts base
00189             dmesh[1] = curIdx-vbase; //verts num
00190         }
00191 
00192         vertices = new float[nverts*3];
00193         ndvertsuniq = curIdx - nverts;
00194         if (ndvertsuniq>0)
00195         {
00196             dvertices = new float[ndvertsuniq*3];
00197         }
00198         for (int vi=0; vi<nAllVerts; vi++)
00199         {
00200             int newIdx = verticesMap[vi];
00201             if (newIdx!=0xffff)
00202             {
00203                 if (newIdx<nverts)
00204                 {
00205                     //navigation mesh vertex
00206                     memcpy(vertices+3*newIdx, allVerts+3*vi, 3*sizeof(float));
00207                 }
00208                 else
00209                 {
00210                     //detailed mesh vertex
00211                     memcpy(dvertices+3*(newIdx-nverts), allVerts+3*vi, 3*sizeof(float));
00212                 }               
00213             }
00214         }
00215 
00216         MEM_freeN(allVerts);
00217     }
00218     else
00219     {
00220         //create from RAS_MeshObject (detailed mesh is fake)
00221         RAS_MeshObject* meshobj = GetMesh(0);
00222         vertsPerPoly = 3;
00223         nverts = meshobj->m_sharedvertex_map.size();
00224         if (nverts >= 0xffff)
00225             return false;
00226         //calculate count of tris
00227         int nmeshpolys = meshobj->NumPolygons();
00228         npolys = nmeshpolys;
00229         for (int p=0; p<nmeshpolys; p++)
00230         {
00231             int vertcount = meshobj->GetPolygon(p)->VertexCount();
00232             npolys+=vertcount-3;
00233         }
00234 
00235         //create verts
00236         vertices = new float[nverts*3];
00237         float* vert = vertices;
00238         for (int vi=0; vi<nverts; vi++)
00239         {
00240             const float* pos = !meshobj->m_sharedvertex_map[vi].empty() ? meshobj->GetVertexLocation(vi) : NULL;
00241             if (pos)
00242                 copy_v3_v3(vert, pos);
00243             else
00244             {
00245                 memset(vert, 0, 3*sizeof(float)); //vertex isn't in any poly, set dummy zero coordinates
00246             }
00247             vert+=3;        
00248         }
00249 
00250         //create tris
00251         polys = new unsigned short[npolys*3*2];
00252         memset(polys, 0xff, sizeof(unsigned short)*3*2*npolys);
00253         unsigned short *poly = polys;
00254         RAS_Polygon* raspoly;
00255         for (int p=0; p<nmeshpolys; p++)
00256         {
00257             raspoly = meshobj->GetPolygon(p);
00258             for (int v=0; v<raspoly->VertexCount()-2; v++)
00259             {
00260                 poly[0]= raspoly->GetVertex(0)->getOrigIndex();
00261                 for (size_t i=1; i<3; i++)
00262                 {
00263                     poly[i]= raspoly->GetVertex(v+i)->getOrigIndex();
00264                 }
00265                 poly += 6;
00266             }
00267         }
00268         dmeshes = NULL;
00269         dvertices = NULL;
00270         ndvertsuniq = 0;
00271         dtris = NULL;
00272         ndtris = npolys;
00273     }
00274     dm->release(dm);
00275     
00276     return true;
00277 }
00278 
00279 
00280 bool KX_NavMeshObject::BuildNavMesh()
00281 {
00282     if (m_navMesh)
00283     {
00284         delete m_navMesh;
00285         m_navMesh = NULL;
00286     }
00287 
00288     if (GetMeshCount()==0)
00289     {
00290         printf("Can't find mesh for navmesh object: %s \n", m_name.ReadPtr());
00291         return false;
00292     }
00293 
00294     float *vertices = NULL, *dvertices = NULL;
00295     unsigned short *polys = NULL, *dtris = NULL, *dmeshes = NULL;
00296     int nverts = 0, npolys = 0, ndvertsuniq = 0, ndtris = 0;    
00297     int vertsPerPoly = 0;
00298     if (!BuildVertIndArrays(vertices, nverts, polys, npolys, 
00299                             dmeshes, dvertices, ndvertsuniq, dtris, ndtris, vertsPerPoly ) 
00300             || vertsPerPoly<3)
00301     {
00302         printf("Can't build navigation mesh data for object:%s \n", m_name.ReadPtr());
00303         return false;
00304     }
00305     
00306     MT_Point3 pos;
00307     if (dmeshes==NULL)
00308     {
00309         for (int i=0; i<nverts; i++)
00310         {
00311             flipAxes(&vertices[i*3]);
00312         }
00313         for (int i=0; i<ndvertsuniq; i++)
00314         {
00315             flipAxes(&dvertices[i*3]);
00316         }
00317     }
00318 
00319     buildMeshAdjacency(polys, npolys, nverts, vertsPerPoly);
00320     
00321     float cs = 0.2f;
00322 
00323     if (!nverts || !npolys)
00324         return false;
00325 
00326     float bmin[3], bmax[3];
00327     calcMeshBounds(vertices, nverts, bmin, bmax);
00328     //quantize vertex pos
00329     unsigned short* vertsi = new unsigned short[3*nverts];
00330     float ics = 1.f/cs;
00331     for (int i=0; i<nverts; i++)
00332     {
00333         vertsi[3*i+0] = static_cast<unsigned short>((vertices[3*i+0]-bmin[0])*ics);
00334         vertsi[3*i+1] = static_cast<unsigned short>((vertices[3*i+1]-bmin[1])*ics);
00335         vertsi[3*i+2] = static_cast<unsigned short>((vertices[3*i+2]-bmin[2])*ics);
00336     }
00337 
00338     // Calculate data size
00339     const int headerSize = sizeof(dtStatNavMeshHeader);
00340     const int vertsSize = sizeof(float)*3*nverts;
00341     const int polysSize = sizeof(dtStatPoly)*npolys;
00342     const int nodesSize = sizeof(dtStatBVNode)*npolys*2;
00343     const int detailMeshesSize = sizeof(dtStatPolyDetail)*npolys;
00344     const int detailVertsSize = sizeof(float)*3*ndvertsuniq;
00345     const int detailTrisSize = sizeof(unsigned char)*4*ndtris;
00346 
00347     const int dataSize = headerSize + vertsSize + polysSize + nodesSize +
00348         detailMeshesSize + detailVertsSize + detailTrisSize;
00349     unsigned char* data = new unsigned char[dataSize];
00350     if (!data)
00351         return false;
00352     memset(data, 0, dataSize);
00353 
00354     unsigned char* d = data;
00355     dtStatNavMeshHeader* header = (dtStatNavMeshHeader*)d; d += headerSize;
00356     float* navVerts = (float*)d; d += vertsSize;
00357     dtStatPoly* navPolys = (dtStatPoly*)d; d += polysSize;
00358     dtStatBVNode* navNodes = (dtStatBVNode*)d; d += nodesSize;
00359     dtStatPolyDetail* navDMeshes = (dtStatPolyDetail*)d; d += detailMeshesSize;
00360     float* navDVerts = (float*)d; d += detailVertsSize;
00361     unsigned char* navDTris = (unsigned char*)d; d += detailTrisSize;
00362 
00363     // Store header
00364     header->magic = DT_STAT_NAVMESH_MAGIC;
00365     header->version = DT_STAT_NAVMESH_VERSION;
00366     header->npolys = npolys;
00367     header->nverts = nverts;
00368     header->cs = cs;
00369     header->bmin[0] = bmin[0];
00370     header->bmin[1] = bmin[1];
00371     header->bmin[2] = bmin[2];
00372     header->bmax[0] = bmax[0];
00373     header->bmax[1] = bmax[1];
00374     header->bmax[2] = bmax[2];
00375     header->ndmeshes = npolys;
00376     header->ndverts = ndvertsuniq;
00377     header->ndtris = ndtris;
00378 
00379     // Store vertices
00380     for (int i = 0; i < nverts; ++i)
00381     {
00382         const unsigned short* iv = &vertsi[i*3];
00383         float* v = &navVerts[i*3];
00384         v[0] = bmin[0] + iv[0] * cs;
00385         v[1] = bmin[1] + iv[1] * cs;
00386         v[2] = bmin[2] + iv[2] * cs;
00387     }
00388     //memcpy(navVerts, vertices, nverts*3*sizeof(float));
00389 
00390     // Store polygons
00391     const unsigned short* src = polys;
00392     for (int i = 0; i < npolys; ++i)
00393     {
00394         dtStatPoly* p = &navPolys[i];
00395         p->nv = 0;
00396         for (int j = 0; j < vertsPerPoly; ++j)
00397         {
00398             if (src[j] == 0xffff) break;
00399             p->v[j] = src[j];
00400             p->n[j] = src[vertsPerPoly+j]+1;
00401             p->nv++;
00402         }
00403         src += vertsPerPoly*2;
00404     }
00405 
00406     header->nnodes = createBVTree(vertsi, nverts, polys, npolys, vertsPerPoly,
00407                                 cs, cs, npolys*2, navNodes);
00408     
00409     
00410     if (dmeshes==NULL)
00411     {
00412         //create fake detail meshes
00413         for (int i = 0; i < npolys; ++i)
00414         {
00415             dtStatPolyDetail& dtl = navDMeshes[i];
00416             dtl.vbase = 0;
00417             dtl.nverts = 0;
00418             dtl.tbase = i;
00419             dtl.ntris = 1;
00420         }
00421         // setup triangles.
00422         unsigned char* tri = navDTris;
00423         for(size_t i=0; i<ndtris; i++)
00424         {
00425             for (size_t j=0; j<3; j++)
00426                 tri[4*i+j] = j;
00427         }
00428     }
00429     else
00430     {
00431         //verts
00432         memcpy(navDVerts, dvertices, ndvertsuniq*3*sizeof(float));
00433         //tris
00434         unsigned char* tri = navDTris;
00435         for(size_t i=0; i<ndtris; i++)
00436         {
00437             for (size_t j=0; j<3; j++)
00438                 tri[4*i+j] = dtris[6*i+j];
00439         }
00440         //detailed meshes
00441         for (int i = 0; i < npolys; ++i)
00442         {
00443             dtStatPolyDetail& dtl = navDMeshes[i];
00444             dtl.vbase = dmeshes[i*4+0];
00445             dtl.nverts = dmeshes[i*4+1];
00446             dtl.tbase = dmeshes[i*4+2];
00447             dtl.ntris = dmeshes[i*4+3];
00448         }       
00449     }
00450 
00451     m_navMesh = new dtStatNavMesh;
00452     m_navMesh->init(data, dataSize, true);  
00453 
00454     delete [] vertices;
00455 
00456     /* navmesh conversion is using C guarded alloc for memory allocaitons */
00457     MEM_freeN(polys);
00458     if (dmeshes) MEM_freeN(dmeshes);
00459     if (dtris) MEM_freeN(dtris);
00460 
00461     if (dvertices)
00462     {
00463         delete [] dvertices;
00464     }
00465 
00466     return true;
00467 }
00468 
00469 dtStatNavMesh* KX_NavMeshObject::GetNavMesh()
00470 {
00471     return m_navMesh;
00472 }
00473 
00474 void KX_NavMeshObject::DrawNavMesh(NavMeshRenderMode renderMode)
00475 {
00476     if (!m_navMesh)
00477         return;
00478     MT_Vector3 color(0.f, 0.f, 0.f);
00479     
00480     switch (renderMode)
00481     {
00482     case RM_POLYS :
00483     case RM_WALLS : 
00484         for (int pi=0; pi<m_navMesh->getPolyCount(); pi++)
00485         {
00486             const dtStatPoly* poly = m_navMesh->getPoly(pi);
00487 
00488             for (int i = 0, j = (int)poly->nv-1; i < (int)poly->nv; j = i++)
00489             {   
00490                 if (poly->n[j] && renderMode==RM_WALLS) 
00491                     continue;
00492                 const float* vif = m_navMesh->getVertex(poly->v[i]);
00493                 const float* vjf = m_navMesh->getVertex(poly->v[j]);
00494                 MT_Point3 vi(vif[0], vif[2], vif[1]);
00495                 MT_Point3 vj(vjf[0], vjf[2], vjf[1]);
00496                 vi = TransformToWorldCoords(vi);
00497                 vj = TransformToWorldCoords(vj);
00498                 KX_RasterizerDrawDebugLine(vi, vj, color);
00499             }
00500         }
00501         break;
00502     case RM_TRIS : 
00503         for (int i = 0; i < m_navMesh->getPolyDetailCount(); ++i)
00504         {
00505             const dtStatPoly* p = m_navMesh->getPoly(i);
00506             const dtStatPolyDetail* pd = m_navMesh->getPolyDetail(i);
00507 
00508             for (int j = 0; j < pd->ntris; ++j)
00509             {
00510                 const unsigned char* t = m_navMesh->getDetailTri(pd->tbase+j);
00511                 MT_Point3 tri[3];
00512                 for (int k = 0; k < 3; ++k)
00513                 {
00514                     const float* v;
00515                     if (t[k] < p->nv)
00516                         v = m_navMesh->getVertex(p->v[t[k]]);
00517                     else
00518                         v =  m_navMesh->getDetailVertex(pd->vbase+(t[k]-p->nv));
00519                     float pos[3];
00520                     rcVcopy(pos, v);
00521                     flipAxes(pos);
00522                     tri[k].setValue(pos);
00523                 }
00524 
00525                 for (int k=0; k<3; k++)
00526                     tri[k] = TransformToWorldCoords(tri[k]);
00527 
00528                 for (int k=0; k<3; k++)
00529                     KX_RasterizerDrawDebugLine(tri[k], tri[(k+1)%3], color);
00530             }
00531         }
00532         break;
00533     default:
00534         /* pass */
00535         break;
00536     }
00537 }
00538 
00539 MT_Point3 KX_NavMeshObject::TransformToLocalCoords(const MT_Point3& wpos)
00540 {
00541     MT_Matrix3x3 orientation = NodeGetWorldOrientation();
00542     const MT_Vector3& scaling = NodeGetWorldScaling();
00543     orientation.scale(scaling[0], scaling[1], scaling[2]);
00544     MT_Transform worldtr(NodeGetWorldPosition(), orientation); 
00545     MT_Transform invworldtr;
00546     invworldtr.invert(worldtr);
00547     MT_Point3 lpos = invworldtr(wpos);
00548     return lpos;
00549 }
00550 
00551 MT_Point3 KX_NavMeshObject::TransformToWorldCoords(const MT_Point3& lpos)
00552 {
00553     MT_Matrix3x3 orientation = NodeGetWorldOrientation();
00554     const MT_Vector3& scaling = NodeGetWorldScaling();
00555     orientation.scale(scaling[0], scaling[1], scaling[2]);
00556     MT_Transform worldtr(NodeGetWorldPosition(), orientation); 
00557     MT_Point3 wpos = worldtr(lpos);
00558     return wpos;
00559 }
00560 
00561 int KX_NavMeshObject::FindPath(const MT_Point3& from, const MT_Point3& to, float* path, int maxPathLen)
00562 {
00563     if (!m_navMesh)
00564         return 0;
00565     MT_Point3 localfrom = TransformToLocalCoords(from);
00566     MT_Point3 localto = TransformToLocalCoords(to); 
00567     float spos[3], epos[3];
00568     localfrom.getValue(spos); flipAxes(spos);
00569     localto.getValue(epos); flipAxes(epos);
00570     dtStatPolyRef sPolyRef = m_navMesh->findNearestPoly(spos, polyPickExt);
00571     dtStatPolyRef ePolyRef = m_navMesh->findNearestPoly(epos, polyPickExt);
00572 
00573     int pathLen = 0;
00574     if (sPolyRef && ePolyRef)
00575     {
00576         dtStatPolyRef* polys = new dtStatPolyRef[maxPathLen];
00577         int npolys;
00578         npolys = m_navMesh->findPath(sPolyRef, ePolyRef, spos, epos, polys, maxPathLen);
00579         if (npolys)
00580         {
00581             pathLen = m_navMesh->findStraightPath(spos, epos, polys, npolys, path, maxPathLen);
00582             for (int i=0; i<pathLen; i++)
00583             {
00584                 flipAxes(&path[i*3]);
00585                 MT_Point3 waypoint(&path[i*3]);
00586                 waypoint = TransformToWorldCoords(waypoint);
00587                 waypoint.getValue(&path[i*3]);
00588             }
00589         }
00590     }
00591 
00592     return pathLen;
00593 }
00594 
00595 float KX_NavMeshObject::Raycast(const MT_Point3& from, const MT_Point3& to)
00596 {
00597     if (!m_navMesh)
00598         return 0.f;
00599     MT_Point3 localfrom = TransformToLocalCoords(from);
00600     MT_Point3 localto = TransformToLocalCoords(to); 
00601     float spos[3], epos[3];
00602     localfrom.getValue(spos); flipAxes(spos);
00603     localto.getValue(epos); flipAxes(epos);
00604     dtStatPolyRef sPolyRef = m_navMesh->findNearestPoly(spos, polyPickExt);
00605     float t=0;
00606     static dtStatPolyRef polys[MAX_PATH_LEN];
00607     m_navMesh->raycast(sPolyRef, spos, epos, t, polys, MAX_PATH_LEN);
00608     return t;
00609 }
00610 
00611 void KX_NavMeshObject::DrawPath(const float *path, int pathLen, const MT_Vector3& color)
00612 {
00613     MT_Vector3 a,b;
00614     for (int i=0; i<pathLen-1; i++)
00615     {
00616         a.setValue(&path[3*i]);
00617         b.setValue(&path[3*(i+1)]);
00618         KX_RasterizerDrawDebugLine(a, b, color);
00619     }
00620 }
00621 
00622 
00623 #ifndef DISABLE_PYTHON
00624 //----------------------------------------------------------------------------
00625 //Python
00626 
00627 PyTypeObject KX_NavMeshObject::Type = {
00628     PyVarObject_HEAD_INIT(NULL, 0)
00629     "KX_NavMeshObject",
00630     sizeof(PyObjectPlus_Proxy),
00631     0,
00632     py_base_dealloc,
00633     0,
00634     0,
00635     0,
00636     0,
00637     py_base_repr,
00638     0,
00639     0,
00640     0,
00641     0,0,0,0,0,0,
00642     Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE,
00643     0,0,0,0,0,0,0,
00644     Methods,
00645     0,
00646     0,
00647     &KX_GameObject::Type,
00648     0,0,0,0,0,0,
00649     py_base_new
00650 };
00651 
00652 PyAttributeDef KX_NavMeshObject::Attributes[] = {
00653     { NULL }    //Sentinel
00654 };
00655 
00656 //KX_PYMETHODTABLE_NOARGS(KX_GameObject, getD),
00657 PyMethodDef KX_NavMeshObject::Methods[] = {
00658     KX_PYMETHODTABLE(KX_NavMeshObject, findPath),
00659     KX_PYMETHODTABLE(KX_NavMeshObject, raycast),
00660     KX_PYMETHODTABLE(KX_NavMeshObject, draw),
00661     KX_PYMETHODTABLE(KX_NavMeshObject, rebuild),
00662     {NULL,NULL} //Sentinel
00663 };
00664 
00665 KX_PYMETHODDEF_DOC(KX_NavMeshObject, findPath,
00666                    "findPath(start, goal): find path from start to goal points\n"
00667                    "Returns a path as list of points)\n")
00668 {
00669     PyObject *ob_from, *ob_to;
00670     if (!PyArg_ParseTuple(args,"OO:getPath",&ob_from,&ob_to))
00671         return NULL;
00672     MT_Point3 from, to;
00673     if (!PyVecTo(ob_from, from) || !PyVecTo(ob_to, to))
00674         return NULL;
00675     
00676     float path[MAX_PATH_LEN*3];
00677     int pathLen = FindPath(from, to, path, MAX_PATH_LEN);
00678     PyObject *pathList = PyList_New( pathLen );
00679     for (int i=0; i<pathLen; i++)
00680     {
00681         MT_Point3 point(&path[3*i]);
00682         PyList_SET_ITEM(pathList, i, PyObjectFrom(point));
00683     }
00684 
00685     return pathList;
00686 }
00687 
00688 KX_PYMETHODDEF_DOC(KX_NavMeshObject, raycast,
00689                    "raycast(start, goal): raycast from start to goal points\n"
00690                    "Returns hit factor)\n")
00691 {
00692     PyObject *ob_from, *ob_to;
00693     if (!PyArg_ParseTuple(args,"OO:getPath",&ob_from,&ob_to))
00694         return NULL;
00695     MT_Point3 from, to;
00696     if (!PyVecTo(ob_from, from) || !PyVecTo(ob_to, to))
00697         return NULL;
00698     float hit = Raycast(from, to);
00699     return PyFloat_FromDouble(hit);
00700 }
00701 
00702 KX_PYMETHODDEF_DOC(KX_NavMeshObject, draw,
00703                    "draw(mode): navigation mesh debug drawing\n"
00704                    "mode: WALLS, POLYS, TRIS\n")
00705 {
00706     int arg;
00707     NavMeshRenderMode renderMode = RM_TRIS;
00708     if (PyArg_ParseTuple(args,"i:rebuild",&arg) && arg>=0 && arg<RM_MAX)
00709         renderMode = (NavMeshRenderMode)arg;
00710     DrawNavMesh(renderMode);
00711     Py_RETURN_NONE;
00712 }
00713 
00714 KX_PYMETHODDEF_DOC_NOARGS(KX_NavMeshObject, rebuild,
00715                           "rebuild(): rebuild navigation mesh\n")
00716 {
00717     BuildNavMesh();
00718     Py_RETURN_NONE;
00719 }
00720 
00721 #endif // DISABLE_PYTHON