void dtNavMesh::queryTiles(const float bmin[3], const float bmax[3], dtTileCallback callback, void * userdata) const { const int tx0 = (int)dtMathFloorf((bmin[0]-m_params.orig[0]) / m_tileWidth); const int tx1 = (int)dtMathFloorf((bmax[0]-m_params.orig[0]) / m_tileWidth); const int ty0 = (int)dtMathFloorf((bmin[2]-m_params.orig[2]) / m_tileHeight); const int ty1 = (int)dtMathFloorf((bmax[2]-m_params.orig[2]) / m_tileHeight); for (int ty = ty0; ty <= ty1; ++ty) { for (int tx = tx0; tx <= tx1; ++tx) { enum { MaxTiles = 32 }; const dtMeshTile * tmpTiles[ MaxTiles ]; const int ntiles = getTilesAt(tx,ty,tmpTiles,MaxTiles); for (int i = 0; i < ntiles; ++i) { if (dtOverlapBounds(bmin,bmax, tmpTiles[ i ]->header->bmin, tmpTiles[ i ]->header->bmax)) { callback( tmpTiles[i], userdata ); } } } } }
dtStatus dtTileCache::queryTiles(const float* bmin, const float* bmax, dtCompressedTileRef* results, int* resultCount, const int maxResults) const { const int MAX_TILES = 32; dtCompressedTileRef tiles[MAX_TILES]; int n = 0; const float tw = m_params.width * m_params.cs; const float th = m_params.height * m_params.cs; const int tx0 = (int)floorf((bmin[0]-m_params.orig[0]) / tw); const int tx1 = (int)floorf((bmax[0]-m_params.orig[0]) / tw); const int ty0 = (int)floorf((bmin[2]-m_params.orig[2]) / th); const int ty1 = (int)floorf((bmax[2]-m_params.orig[2]) / th); for (int ty = ty0; ty <= ty1; ++ty) { for (int tx = tx0; tx <= tx1; ++tx) { const int ntiles = getTilesAt(tx,ty,tiles,MAX_TILES); for (int i = 0; i < ntiles; ++i) { const dtCompressedTile* tile = &m_tiles[decodeTileIdTile(tiles[i])]; float tbmin[3], tbmax[3]; calcTightTileBounds(tile->header, tbmin, tbmax); if (dtOverlapBounds(bmin,bmax, tbmin,tbmax)) { if (n < maxResults) results[n++] = tiles[i]; } } } } *resultCount = n; return DT_SUCCESS; }
int dtNavMesh::queryPolygonsInTile(const dtMeshTile* tile, const float* qmin, const float* qmax, dtPolyRef* polys, const int maxPolys) const { if (tile->bvTree) { const dtBVNode* node = &tile->bvTree[0]; const dtBVNode* end = &tile->bvTree[tile->header->bvNodeCount]; const float* tbmin = tile->header->bmin; const float* tbmax = tile->header->bmax; const float qfac = tile->header->bvQuantFactor; // Calculate quantized box unsigned short bmin[3], bmax[3]; // dtClamp query box to world box. float minx = dtClamp(qmin[0], tbmin[0], tbmax[0]) - tbmin[0]; float miny = dtClamp(qmin[1], tbmin[1], tbmax[1]) - tbmin[1]; float minz = dtClamp(qmin[2], tbmin[2], tbmax[2]) - tbmin[2]; float maxx = dtClamp(qmax[0], tbmin[0], tbmax[0]) - tbmin[0]; float maxy = dtClamp(qmax[1], tbmin[1], tbmax[1]) - tbmin[1]; float maxz = dtClamp(qmax[2], tbmin[2], tbmax[2]) - tbmin[2]; // Quantize bmin[0] = (unsigned short)(qfac * minx) & 0xfffe; bmin[1] = (unsigned short)(qfac * miny) & 0xfffe; bmin[2] = (unsigned short)(qfac * minz) & 0xfffe; bmax[0] = (unsigned short)(qfac * maxx + 1) | 1; bmax[1] = (unsigned short)(qfac * maxy + 1) | 1; bmax[2] = (unsigned short)(qfac * maxz + 1) | 1; // Traverse tree dtPolyRef base = getPolyRefBase(tile); int n = 0; while (node < end) { const bool overlap = dtOverlapQuantBounds(bmin, bmax, node->bmin, node->bmax); const bool isLeafNode = node->i >= 0; if (isLeafNode && overlap) { if (n < maxPolys) polys[n++] = base | (dtPolyRef)node->i; } if (overlap || isLeafNode) node++; else { const int escapeIndex = -node->i; node += escapeIndex; } } return n; } else { float bmin[3], bmax[3]; int n = 0; dtPolyRef base = getPolyRefBase(tile); for (int i = 0; i < tile->header->polyCount; ++i) { dtPoly* p = &tile->polys[i]; // Do not return off-mesh connection polygons. if (p->getType() == DT_POLYTYPE_OFFMESH_CONNECTION) continue; // Calc polygon bounds. const float* v = &tile->verts[p->verts[0]*3]; dtVcopy(bmin, v); dtVcopy(bmax, v); for (int j = 1; j < p->vertCount; ++j) { v = &tile->verts[p->verts[j]*3]; dtVmin(bmin, v); dtVmax(bmax, v); } if (dtOverlapBounds(qmin,qmax, bmin,bmax)) { if (n < maxPolys) polys[n++] = base | (dtPolyRef)i; } } return n; } }