Blender V2.61 - r43446
|
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