bool PathInfo::isPointInPolyBounds(float x, float y, float z, float &distance, dtPolyRef polyRef) { float point[3] = {y, z, x}; int polyindex; const dtMeshTile* tile = m_navMesh->getTileByPolyRef(polyRef, &polyindex); if(!tile) return false; const dtPoly poly = tile->polys[polyindex]; float vertices[DT_VERTS_PER_POLYGON*3]; float ed[DT_VERTS_PER_POLYGON]; // distance^2 from edge to point float et[DT_VERTS_PER_POLYGON]; // describes where on edge is nearest point // Collect vertices. int nv = 0; for (int i = 0; i < (int)poly.vertCount; ++i) { rcVcopy(&vertices[nv*3], &tile->verts[poly.verts[i]*3]); nv++; } bool isInsidePoly = dtDistancePtPolyEdgesSqr(point, vertices, nv, ed, et); if(!isInsidePoly) { // distance to nearest edge distance = FLT_MAX; for(int i = 0; i < (int)poly.vertCount; ++i) if(ed[i] < distance) distance = ed[i]; } else distance = 0.0f; return isInsidePoly; }
void dtNavMesh::closestPointOnPoly(dtPolyRef ref, const float* pos, float* closest, bool* posOverPoly) const { const dtMeshTile* tile = 0; const dtPoly* poly = 0; getTileAndPolyByRefUnsafe(ref, &tile, &poly); // Off-mesh connections don't have detail polygons. if (poly->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) { const float* v0 = &tile->verts[poly->verts[0]*3]; const float* v1 = &tile->verts[poly->verts[1]*3]; const float d0 = dtVdist(pos, v0); const float d1 = dtVdist(pos, v1); const float u = d0 / (d0+d1); dtVlerp(closest, v0, v1, u); if (posOverPoly) *posOverPoly = false; return; } const unsigned int ip = (unsigned int)(poly - tile->polys); const dtPolyDetail* pd = &tile->detailMeshes[ip]; // Clamp point to be inside the polygon. float verts[DT_VERTS_PER_POLYGON*3]; float edged[DT_VERTS_PER_POLYGON]; float edget[DT_VERTS_PER_POLYGON]; const int nv = poly->vertCount; for (int i = 0; i < nv; ++i) dtVcopy(&verts[i*3], &tile->verts[poly->verts[i]*3]); dtVcopy(closest, pos); if (!dtDistancePtPolyEdgesSqr(pos, verts, nv, edged, edget)) { // Point is outside the polygon, dtClamp to nearest edge. float dmin = FLT_MAX; int imin = -1; for (int i = 0; i < nv; ++i) { if (edged[i] < dmin) { dmin = edged[i]; imin = i; } } const float* va = &verts[imin*3]; const float* vb = &verts[((imin+1)%nv)*3]; dtVlerp(closest, va, vb, edget[imin]); if (posOverPoly) *posOverPoly = false; } else { if (posOverPoly) *posOverPoly = true; } // Find height at the location. for (int j = 0; j < pd->triCount; ++j) { const unsigned char* t = &tile->detailTris[(pd->triBase+j)*4]; const float* v[3]; for (int k = 0; k < 3; ++k) { if (t[k] < poly->vertCount) v[k] = &tile->verts[poly->verts[t[k]]*3]; else v[k] = &tile->detailVerts[(pd->vertBase+(t[k]-poly->vertCount))*3]; } float h; if (dtClosestHeightPointTriangle(pos, v[0], v[1], v[2], h)) { closest[1] = h; break; } } }