Advertisement
Guest User

NavMesher.cpp

a guest
Jun 25th, 2014
290
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 15.94 KB | None | 0 0
  1. #include "NavMesher.h"
  2.  
  3. NavMesher::NavMesher(LPDIRECT3DDEVICE9 device)
  4. {
  5.     m_d3d9device = device;
  6.     m_d3d9device->AddRef();
  7.     m_buildOpts.m_cellSize             = 0.1f;//0.3f;
  8.     m_buildOpts.m_cellHeight           = 0.1f;//0.2f;
  9.     m_buildOpts.m_agentHeight          = 2.0f;
  10.     m_buildOpts.m_agentRadius          = 0.4f;
  11.     m_buildOpts.m_agentMaxClimb        = 0.2f;//0.9f;
  12.     m_buildOpts.m_agentMaxSlope        = 45.0f;
  13.     m_buildOpts.m_regionMinSize        = 8;
  14.     m_buildOpts.m_regionMergeSize      = 20;
  15.     m_buildOpts.m_monotonePartitioning = false;
  16.     m_buildOpts.m_edgeMaxLen           = 12.0f;
  17.     m_buildOpts.m_edgeMaxError         = 1.3f;
  18.     m_buildOpts.m_vertsPerPoly         = 6.0f;
  19.     m_buildOpts.m_detailSampleDist     = 6.0f;
  20.     m_buildOpts.m_detailSampleMaxError = 1.0f;
  21. }
  22.  
  23. NavMesher::~NavMesher()
  24. {
  25.     m_dxDebugMesh->Release();
  26.     dtFreeNavMesh(m_navMesh);
  27.     dtFreeNavMeshQuery(m_navQuery);
  28.     m_d3d9device->Release();
  29. }
  30.  
  31. bool NavMesher::buildNavMesh(LPD3DXMESH fromMesh)
  32. {
  33.     std::vector<float> vVerts;
  34.     std::vector<int> vTris;
  35.     extractMeshData(fromMesh, vVerts, vTris);
  36.  
  37.     float* verts = &vVerts[0];
  38.     int* tris    = &vTris[0];
  39.     int nverts   = vVerts.size() / 3;
  40.     int ntris    = vTris.size() / 3;
  41.  
  42.     rcCalcBounds(verts, nverts, m_boundsMin, m_boundsMax);
  43.  
  44.     //
  45.     // Step 1. Initialize build config.
  46.     //
  47.     rcConfig cfg;
  48.     memset(&cfg, 0, sizeof(cfg));
  49.     cfg.cs                      = m_buildOpts.m_cellSize;
  50.     cfg.ch                      = m_buildOpts.m_cellHeight;
  51.     cfg.walkableSlopeAngle      = m_buildOpts.m_agentMaxSlope;
  52.     cfg.walkableHeight          = (int)ceilf(m_buildOpts.m_agentHeight / cfg.ch);
  53.     cfg.walkableClimb           = (int)floorf(m_buildOpts.m_agentMaxClimb / cfg.ch);
  54.     cfg.walkableRadius          = (int)ceilf(m_buildOpts.m_agentRadius / cfg.cs);
  55.     cfg.maxEdgeLen              = (int)(m_buildOpts.m_edgeMaxLen / m_buildOpts.m_cellSize);
  56.     cfg.maxSimplificationError  = m_buildOpts.m_edgeMaxError;
  57.     cfg.minRegionArea           = (int)rcSqr(m_buildOpts.m_regionMinSize);      // Note: area = size*size
  58.     cfg.mergeRegionArea         = (int)rcSqr(m_buildOpts.m_regionMergeSize);  // Note: area = size*size
  59.     cfg.maxVertsPerPoly         = (int)m_buildOpts.m_vertsPerPoly;
  60.     cfg.detailSampleDist        = m_buildOpts.m_detailSampleDist < 0.9f ? 0 : m_buildOpts.m_cellSize * m_buildOpts.m_detailSampleDist;
  61.     cfg.detailSampleMaxError    = m_buildOpts.m_cellHeight * m_buildOpts.m_detailSampleMaxError;
  62.  
  63.     // Set the area where the navigation will be build.
  64.     // Here the bounds of the input mesh are used, but the
  65.     // area could be specified by an user defined box, etc.
  66.     rcVcopy(cfg.bmin, m_boundsMin);
  67.     rcVcopy(cfg.bmax, m_boundsMax);
  68.     rcCalcGridSize(cfg.bmin, cfg.bmax, cfg.cs, &cfg.width, &cfg.height);
  69.  
  70.     rcContext* ctx = new rcContext(); // set your own "context", this does nothing
  71.     ctx->resetTimers();
  72.     ctx->startTimer(RC_TIMER_TOTAL);
  73.  
  74.     //
  75.     // Step 2. Rasterize input polygon soup.
  76.     //
  77.     rcHeightfield* pHeightfield = rcAllocHeightfield();
  78.     if(!pHeightfield)
  79.     {
  80.         MessageBox(0,"buildNavigation: Out of memory 'solid'.",0,0);
  81.         return false;
  82.     }
  83.     if (!rcCreateHeightfield(ctx, *pHeightfield, cfg.width, cfg.height, cfg.bmin, cfg.bmax, cfg.cs, cfg.ch))
  84.     {
  85.         MessageBox(0,"buildNavigation: Could not create solid heightfield.",0,0);
  86.         return false;
  87.     }
  88.  
  89.     // Allocate array that can hold triangle area types.
  90.     // If you have multiple meshes you need to process, allocate
  91.     // and array which can hold the max number of triangles you need to process.
  92.     //unsigned char* pTriAreas = new unsigned char[ntris];
  93.     unsigned char* pTriAreas = new unsigned char[ntris];
  94.     if(!pTriAreas)
  95.     {
  96.         MessageBox(0,"buildNavigation: Out of memory 'pTriAreas' (%d).", 0,0);
  97.         return false;
  98.     }
  99.  
  100.     // Find triangles which are walkable based on their slope and rasterize them.
  101.     // If your input data is multiple meshes, you can transform them here, calculate
  102.     // the are type for each of the meshes and rasterize them.
  103.     memset(pTriAreas, 0, ntris);
  104.     rcMarkWalkableTriangles(ctx, cfg.walkableSlopeAngle, verts, nverts, tris, ntris, pTriAreas);
  105.     rcRasterizeTriangles(ctx, verts, nverts, tris, pTriAreas, ntris, *pHeightfield, cfg.walkableClimb);
  106.  
  107.     delete [] pTriAreas;
  108.     pTriAreas = nullptr;
  109.  
  110.     //
  111.     // Step 3. Filter walkables surfaces.
  112.     //
  113.     // Once all geoemtry is rasterized, we do initial pass of filtering to
  114.     // remove unwanted overhangs caused by the conservative rasterization
  115.     // as well as filter spans where the character cannot possibly stand.
  116.     rcFilterLowHangingWalkableObstacles(ctx, cfg.walkableClimb, *pHeightfield);
  117.     rcFilterLedgeSpans(ctx, cfg.walkableHeight, cfg.walkableClimb, *pHeightfield);
  118.     rcFilterWalkableLowHeightSpans(ctx, cfg.walkableHeight, *pHeightfield);
  119.  
  120.     //
  121.     // Step 4. Partition walkable surface to simple regions.
  122.     //
  123.     // Compact the heightfield so that it is faster to handle from now on.
  124.     // This will result more cache coherent data as well as the neighbours
  125.     // between walkable cells will be calculated.
  126.     rcCompactHeightfield* pCmpHeightfield = rcAllocCompactHeightfield();
  127.     if(!pCmpHeightfield)
  128.     {
  129.         MessageBox(0,"buildNavigation: Out of memory 'chf'.",0,0);
  130.         return false;
  131.     }
  132.     if (!rcBuildCompactHeightfield(ctx, cfg.walkableHeight, cfg.walkableClimb, *pHeightfield, *pCmpHeightfield))
  133.     {
  134.         MessageBox(0,"buildNavigation: Could not build compact data.",0,0);
  135.         return false;
  136.     }
  137.  
  138.     rcFreeHeightField(pHeightfield);
  139.     pHeightfield = nullptr;
  140.  
  141.     // Erode the walkable area by agent radius.
  142.     if(!rcErodeWalkableArea(ctx, cfg.walkableRadius, *pCmpHeightfield))
  143.     {
  144.         MessageBox(0,"buildNavigation: Could not erode.",0,0);
  145.         return false;
  146.     }
  147.  
  148.     // Prepare for region partitioning, by calculating distance field along the walkable surface.
  149.     if (!rcBuildDistanceField(ctx, *pCmpHeightfield))
  150.     {
  151.         MessageBox(0, "buildNavigation: Could not build distance field.",0,0);
  152.         return false;
  153.     }
  154.  
  155.     // Partition the walkable surface into simple regions without holes.
  156.     if (!rcBuildRegions(ctx, *pCmpHeightfield, 0, cfg.minRegionArea, cfg.mergeRegionArea))
  157.     {
  158.         MessageBox(0, "buildNavigation: Could not build regions.",0,0);
  159.         return false;
  160.     }
  161.  
  162.     //
  163.     // Step 5. Trace and simplify region contours.
  164.     //
  165.     // Create contours.
  166.     rcContourSet* pContourSet = rcAllocContourSet();
  167.     if(!pContourSet)
  168.     {
  169.         MessageBox(0,"buildNavigation: Out of memory 'cset'.",0,0);
  170.         return false;
  171.     }
  172.     if(!rcBuildContours(ctx, *pCmpHeightfield, cfg.maxSimplificationError, cfg.maxEdgeLen, *pContourSet))
  173.     {
  174.         MessageBox(0,"buildNavigation: Could not create contours.",0,0);
  175.         return false;
  176.     }
  177.    
  178.     //
  179.     // Step 6. Build polygons mesh from contours.
  180.     //
  181.     // Build polygon navmesh from the contours.
  182.     rcPolyMesh* pPolyMesh = rcAllocPolyMesh();
  183.     if(!pPolyMesh)
  184.     {
  185.         MessageBox(0,"buildNavigation: Out of memory 'pmesh'.",0,0);
  186.         return false;
  187.     }
  188.     if(!rcBuildPolyMesh(ctx, *pContourSet, cfg.maxVertsPerPoly, *pPolyMesh))
  189.     {
  190.         MessageBox(0,"buildNavigation: Could not triangulate contours.",0,0);
  191.         return false;
  192.     }
  193.  
  194.     //
  195.     // Step 7. Create detail mesh which allows to access approximate height on each polygon.
  196.     //
  197.     rcPolyMeshDetail* pDetailMesh = rcAllocPolyMeshDetail();
  198.     if(!pDetailMesh)
  199.     {
  200.         MessageBox(0,"buildNavigation: Out of memory 'pmdtl'.",0,0);
  201.         return false;
  202.     }
  203.  
  204.     if(!rcBuildPolyMeshDetail(ctx, *pPolyMesh, *pCmpHeightfield, cfg.detailSampleDist, cfg.detailSampleMaxError, *pDetailMesh))
  205.     {
  206.         MessageBox(0,"buildNavigation: Could not build detail mesh.",0,0);
  207.         return false;
  208.     }
  209.  
  210.     rcFreeCompactHeightfield(pCmpHeightfield);
  211.     pCmpHeightfield = nullptr;
  212.     rcFreeContourSet(pContourSet);
  213.     pContourSet = nullptr;
  214.  
  215.     // At this point the navigation mesh data is ready, you can access it from m_pmesh.
  216.     // See duDebugDrawPolyMesh or dtCreateNavMeshData as examples how to access the data.
  217.     //
  218.     // (Optional) Step 8. Create Detour data from Recast poly mesh.
  219.     //
  220.     // The GUI may allow more max points per polygon than Detour can handle.
  221.     // Only build the detour navmesh if we do not exceed the limit.
  222.     if(cfg.maxVertsPerPoly <= DT_VERTS_PER_POLYGON)
  223.     {
  224.         // Update poly flags from areas.
  225.         for(int i = 0; i < pPolyMesh->npolys; ++i)
  226.         {
  227.             if(pPolyMesh->areas[i] == RC_WALKABLE_AREA)
  228.                 pPolyMesh->areas[i] = SAMPLE_POLYAREA_GROUND;
  229.  
  230.             if(pPolyMesh->areas[i] == SAMPLE_POLYAREA_GROUND ||
  231.                 pPolyMesh->areas[i] == SAMPLE_POLYAREA_GRASS ||
  232.                 pPolyMesh->areas[i] == SAMPLE_POLYAREA_ROAD)
  233.             {
  234.                 pPolyMesh->flags[i] = SAMPLE_POLYFLAGS_WALK;
  235.             }
  236.             else if(pPolyMesh->areas[i] == SAMPLE_POLYAREA_WATER)
  237.             {
  238.                 pPolyMesh->flags[i] = SAMPLE_POLYFLAGS_SWIM;
  239.             }
  240.             else if(pPolyMesh->areas[i] == SAMPLE_POLYAREA_DOOR)
  241.             {
  242.                 pPolyMesh->flags[i] = SAMPLE_POLYFLAGS_WALK | SAMPLE_POLYFLAGS_DOOR;
  243.             }
  244.         }
  245.  
  246.         dtNavMeshCreateParams params;
  247.         memset(&params, 0, sizeof(params));
  248.         params.verts            = pPolyMesh->verts;
  249.         params.vertCount        = pPolyMesh->nverts;
  250.         params.polys            = pPolyMesh->polys;
  251.         params.polyAreas        = pPolyMesh->areas;
  252.         params.polyFlags        = pPolyMesh->flags;
  253.         params.polyCount        = pPolyMesh->npolys;
  254.         params.nvp              = pPolyMesh->nvp;
  255.         params.detailMeshes     = pDetailMesh->meshes;
  256.         params.detailVerts      = pDetailMesh->verts;
  257.         params.detailVertsCount = pDetailMesh->nverts;
  258.         params.detailTris       = pDetailMesh->tris;
  259.         params.detailTriCount   = pDetailMesh->ntris;
  260.  
  261.         params.offMeshConAreas  = 0;
  262.         params.offMeshConCount  = 0;
  263.         params.offMeshConDir    = 0;
  264.         params.offMeshConFlags  = 0;
  265.         params.offMeshConRad    = 0;
  266.         params.offMeshConUserID = 0;
  267.         params.offMeshConVerts  = 0;
  268.  
  269.         params.walkableHeight   = m_buildOpts.m_agentHeight;
  270.         params.walkableRadius   = m_buildOpts.m_agentRadius;
  271.         params.walkableClimb    = m_buildOpts.m_agentMaxClimb;
  272.         rcVcopy(params.bmin, pPolyMesh->bmin);
  273.         rcVcopy(params.bmax, pPolyMesh->bmax);
  274.         params.cs = cfg.cs;
  275.         params.ch = cfg.ch;
  276.         params.buildBvTree = true;
  277.  
  278.         unsigned char* navData = 0;
  279.         int navDataSize = 0;
  280.         if(!dtCreateNavMeshData(&params, &navData, &navDataSize))
  281.         {
  282.             MessageBox(0,"Could not build Detour navmesh.",0,0);
  283.             return false;
  284.         }
  285.  
  286.         m_navMesh = dtAllocNavMesh();
  287.         if(!m_navMesh)
  288.         {
  289.             dtFree(navData);
  290.             MessageBox(0, "Could not create Detour navmesh",0,0);
  291.             return false;
  292.         }
  293.  
  294.         dtStatus status;
  295.  
  296.         status = m_navMesh->init(navData, navDataSize, DT_TILE_FREE_DATA);
  297.         if (dtStatusFailed(status))
  298.         {
  299.             dtFree(navData);
  300.             MessageBox(0,"Could not init Detour navmesh",0,0);
  301.             return false;
  302.         }
  303.  
  304.         m_navQuery = dtAllocNavMeshQuery();
  305.         status = m_navQuery->init(m_navMesh, 2048);
  306.         if(dtStatusFailed(status))
  307.         {
  308.             MessageBox(0,"Could not init Detour navmesh query",0,0);
  309.             return false;
  310.         }
  311.     }
  312.  
  313.     ctx->stopTimer(RC_TIMER_TOTAL);
  314.  
  315.     buildDebugMesh(pDetailMesh);
  316.  
  317.     rcFreePolyMesh(pPolyMesh);
  318.     rcFreePolyMeshDetail(pDetailMesh);
  319.     delete ctx;
  320.     return true;
  321. }
  322.  
  323. bool NavMesher::extractMeshData(LPD3DXMESH dxMesh, std::vector<float>& verts, std::vector<int>& tris)
  324. {
  325.     D3DVERTEXELEMENT9 decl[MAXD3DDECLLENGTH];
  326.     dxMesh->GetDeclaration(decl);
  327.  
  328.     WORD offsetToPosition = 0;
  329.  
  330.     for (UINT i = 0; i < MAXD3DDECLLENGTH; ++i)
  331.     {
  332.         if (D3DDECLUSAGE_POSITION == decl[i].Usage)
  333.         {
  334.             offsetToPosition = decl[i].Offset;
  335.         }
  336.     }
  337.  
  338.     DWORD opt        = dxMesh->GetOptions();
  339.     DWORD indStride  = (opt & D3DXMESH_32BIT) ? sizeof(DWORD) : sizeof(WORD);
  340.     DWORD numInd     = dxMesh->GetNumFaces() * 3;
  341.     DWORD vertStride = dxMesh->GetNumBytesPerVertex();
  342.     DWORD numVerts   = dxMesh->GetNumVertices();
  343.  
  344.     BYTE* pInd;
  345.     BYTE* pVert;
  346.     dxMesh->LockVertexBuffer(0, (LPVOID*)&pVert);
  347.     dxMesh->LockIndexBuffer(0, (LPVOID*)&pInd);
  348.  
  349.     for (int i = 0; i < int(numVerts); ++i)
  350.     {
  351.         D3DXVECTOR3 pos = *(D3DXVECTOR3*)(&pVert[vertStride * i + offsetToPosition]);
  352.         verts.push_back(pos.x);
  353.         verts.push_back(pos.y);
  354.         verts.push_back(pos.z);
  355.     }
  356.  
  357.     for (int i = 0; i < int(numInd); i += 3)
  358.     {
  359.         int inx0, inx1, inx2;
  360.         if (sizeof(DWORD) == indStride)
  361.         {
  362.             inx0 = *(int*)(&pInd[indStride * (i + 0)]);
  363.             inx1 = *(int*)(&pInd[indStride * (i + 1)]);
  364.             inx2 = *(int*)(&pInd[indStride * (i + 2)]);
  365.         }
  366.         else
  367.         {
  368.             inx0 = *(WORD*)(&pInd[indStride * (i + 0)]);
  369.             inx1 = *(WORD*)(&pInd[indStride * (i + 1)]);
  370.             inx2 = *(WORD*)(&pInd[indStride * (i + 2)]);
  371.         }
  372.         tris.push_back(inx0);
  373.         tris.push_back(inx1);
  374.         tris.push_back(inx2);
  375.     }
  376.  
  377.     dxMesh->UnlockVertexBuffer();
  378.     dxMesh->UnlockIndexBuffer();
  379.  
  380.     return true;
  381. }
  382.  
  383. bool NavMesher::buildDebugMesh(rcPolyMeshDetail* dmesh)
  384. {
  385.     if(dmesh->nmeshes == 0)
  386.     {
  387.         MessageBox(0,"getMeshDataFromPolyMeshDetail(): dmesh->nmeshes == 0\n", 0,0);
  388.         return false;
  389.     }
  390.  
  391.     D3DVERTEXELEMENT9 vertexElements[] =
  392.     {
  393.         {0, 0,  D3DDECLTYPE_FLOAT3,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0},
  394.         {0, 12, D3DDECLTYPE_FLOAT3,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_NORMAL,   0},
  395.         {0, 24, D3DDECLTYPE_FLOAT2,  D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0},
  396.         D3DDECL_END()
  397.     };
  398.  
  399.     if(FAILED(D3DXCreateMesh(dmesh->ntris, dmesh->nverts, D3DXMESH_MANAGED, vertexElements, d3d9device, &m_dxDebugMesh)))
  400.     {
  401.         MessageBox(0, "Failed to create dx mesh!", 0, 0);
  402.         return false;
  403.     }
  404.  
  405.     struct VERTEX
  406.     {
  407.         D3DXVECTOR3 p;
  408.         D3DXVECTOR3 n;
  409.         D3DXVECTOR2 t;
  410.     };
  411.     WORD* pInd;
  412.     VERTEX* pVert;
  413.  
  414.     m_dxDebugMesh->LockVertexBuffer(0, (LPVOID*)&pVert);
  415.     m_dxDebugMesh->LockIndexBuffer(0, (LPVOID*)&pInd);
  416.  
  417.     const D3DXVECTOR3* verts = (const D3DXVECTOR3*)dmesh->verts;
  418.     for(int i = 0; i < dmesh->nverts; ++i)
  419.     {
  420.         pVert[i].p = verts[i];
  421.         pVert[i].n = D3DXVECTOR3(0.f,0.0f,0.0f); // temp
  422.         pVert[i].t = D3DXVECTOR2(0.0f,0.0f); // temp
  423.     }
  424.  
  425.     // does not work like this!
  426.     /*const unsigned char* tris = dmesh->tris;
  427.     for(int i = 0; i < dmesh->ntris * 3; ++i)
  428.     {
  429.         pInd[i] = tris[i];
  430.     }*/
  431.    
  432.     // this is piece of code for indices found on Irrlicht forum
  433.     int cnt = 0;
  434.     int tri_offset = 0;
  435.     int old_nverts = 0;
  436.     for (int p = 0; p < dmesh->nmeshes; ++p)
  437.     {
  438.         unsigned int* m = &(dmesh->meshes[p * 4]);
  439.         const unsigned short bverts = m[0]; // `b' means "beginning of"!!
  440.         const unsigned short nverts = m[1];
  441.         const unsigned short btris  = m[2];
  442.         const unsigned short ntris  = m[3];
  443.         const unsigned char* tris   = &(dmesh->tris[btris * 4]);
  444.  
  445.         tri_offset += old_nverts;
  446.  
  447.         for(int n = 0; n < ntris; ++n)
  448.         {
  449.             for(int k = 0; k < 3; ++k)
  450.             {
  451.                 int tri = tris[n * 4 + k] + tri_offset;
  452.                 pInd[cnt] = tri;
  453.                 cnt++;
  454.             }
  455.         }
  456.         old_nverts = nverts;
  457.     }
  458.  
  459.     m_dxDebugMesh->UnlockVertexBuffer();
  460.     m_dxDebugMesh->UnlockIndexBuffer();
  461.  
  462.     return true;
  463. }
  464.  
  465. void NavMesher::togglePolyActiveState(float* p)
  466. {
  467.     dtNavMesh* nav = m_navMesh;
  468.     dtNavMeshQuery* navquery = m_navQuery;
  469.     if (nav && navquery)
  470.     {
  471.         dtQueryFilter filter;
  472.         float ext[3] = { 2.0f, 4.0f, 2.0f };
  473.         float tgt[3];
  474.         dtPolyRef ref;
  475.         navquery->findNearestPoly(p, ext, &filter, &ref, tgt);
  476.         if (ref)
  477.         {
  478.             unsigned short flags = 0;
  479.             if (dtStatusSucceed(nav->getPolyFlags(ref, &flags)))
  480.             {
  481.                 flags ^= SAMPLE_POLYFLAGS_DISABLED;
  482.                 nav->setPolyFlags(ref, flags);
  483.             }
  484.         }
  485.     }
  486. }
  487.  
  488. bool NavMesher::findPath(const D3DXVECTOR3& from, const D3DXVECTOR3& to, NavPath* path)
  489. {
  490.     if(nullptr == m_navQuery)
  491.     {
  492.         return false;
  493.     }
  494.     if(nullptr == m_navMesh)
  495.     {
  496.         return  false;
  497.     }
  498.  
  499.     dtQueryFilter queryFilter;
  500.     dtPolyRef startRef;
  501.     dtPolyRef endRef;
  502.  
  503.     dtPolyRef returnedPath[MAX_PATH_NODES];
  504.     float extents[3];
  505.     extents[0] = 2.f;
  506.     extents[1] = 4.f;
  507.     extents[2] = 2.f;
  508.  
  509.  
  510.     m_navQuery->findNearestPoly(from, extents, &queryFilter, &startRef, 0);
  511.     if (startRef == 0)
  512.     {
  513.         return false;
  514.  
  515.     }
  516.     m_navQuery->findNearestPoly(to, extents, &queryFilter, &endRef, 0);
  517.     if (endRef == 0)
  518.     {
  519.         return false;
  520.  
  521.     }
  522.     dtStatus findStatus = DT_FAILURE;
  523.     int pathCount;
  524.  
  525.     findStatus = m_navQuery->findPath(startRef, endRef, from, to, &queryFilter, returnedPath, &pathCount, MAX_PATH_NODES);
  526.     if (dtStatusFailed(findStatus))
  527.     {
  528.         return false;
  529.     }
  530.  
  531.     if(pathCount > 0)
  532.     {
  533.         int numNodes = 0;
  534.         findStatus = m_navQuery->findStraightPath(from, to, returnedPath, pathCount, path->pos, 0, 0, &numNodes, MAX_PATH_NODES);
  535.         if(dtStatusFailed(findStatus))
  536.         {
  537.             return false;
  538.         }
  539.         path->count = numNodes;
  540.     }
  541.     return true;
  542. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement