void HierarchicalPathfinder::Recompute(Grid<NavcellData>* grid, const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks, const std::map<std::string, pass_class_t>& pathfindingPassClassMasks) { PROFILE3("Hierarchical Recompute"); m_PassClassMasks = pathfindingPassClassMasks; std::map<std::string, pass_class_t> allPassClasses = m_PassClassMasks; allPassClasses.insert(nonPathfindingPassClassMasks.begin(), nonPathfindingPassClassMasks.end()); m_W = grid->m_W; m_H = grid->m_H; // Divide grid into chunks with round-to-positive-infinity m_ChunksW = (grid->m_W + CHUNK_SIZE - 1) / CHUNK_SIZE; m_ChunksH = (grid->m_H + CHUNK_SIZE - 1) / CHUNK_SIZE; ENSURE(m_ChunksW < 256 && m_ChunksH < 256); // else the u8 Chunk::m_ChunkI will overflow m_Chunks.clear(); m_Edges.clear(); for (auto& passClassMask : allPassClasses) { pass_class_t passClass = passClassMask.second; // Compute the regions within each chunk m_Chunks[passClass].resize(m_ChunksW*m_ChunksH); for (int cj = 0; cj < m_ChunksH; ++cj) { for (int ci = 0; ci < m_ChunksW; ++ci) { m_Chunks[passClass].at(cj*m_ChunksW + ci).InitRegions(ci, cj, grid, passClass); } } // Construct the search graph over the regions EdgesMap& edges = m_Edges[passClass]; for (int cj = 0; cj < m_ChunksH; ++cj) { for (int ci = 0; ci < m_ChunksW; ++ci) { FindEdges(ci, cj, passClass, edges); } } } if (m_DebugOverlay) { PROFILE("debug overlay"); m_DebugOverlayLines.clear(); AddDebugEdges(GetPassabilityClass("default")); } }
void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid) { PROFILE3("Hierarchical Update"); std::vector<std::pair<int, int> > processedChunks; for (int j = 0; j < dirtinessGrid.m_H; ++j) { for (int i = 0; i < dirtinessGrid.m_W; ++i) { if (!dirtinessGrid.get(i, j)) continue; std::pair<int, int> chunkID(i / CHUNK_SIZE, j / CHUNK_SIZE); for (auto& passClassMask : m_PassClassMasks) { pass_class_t passClass = passClassMask.second; Chunk& a = m_Chunks[passClass].at(chunkID.second*m_ChunksW + chunkID.first); if (std::find(processedChunks.begin(), processedChunks.end(), chunkID) == processedChunks.end()) { processedChunks.push_back(chunkID); a.InitRegions(chunkID.first, chunkID.second, grid, passClass); } } } } // TODO: Also be clever with edges m_Edges.clear(); for (auto& passClassMask : m_PassClassMasks) { pass_class_t passClass = passClassMask.second; EdgesMap& edges = m_Edges[passClass]; for (int cj = 0; cj < m_ChunksH; ++cj) { for (int ci = 0; ci < m_ChunksW; ++ci) { FindEdges(ci, cj, passClass, edges); } } } if (m_DebugOverlay) { PROFILE("debug overlay"); m_DebugOverlayLines.clear(); AddDebugEdges(GetPassabilityClass("default")); } }
void HierarchicalPathfinder::SetDebugOverlay(bool enabled, const CSimContext* simContext) { if (enabled && !m_DebugOverlay) { m_DebugOverlay = new HierarchicalOverlay(*this); m_DebugOverlayLines.clear(); m_SimContext = simContext; AddDebugEdges(GetPassabilityClass("default")); } else if (!enabled && m_DebugOverlay) { SAFE_DELETE(m_DebugOverlay); m_DebugOverlayLines.clear(); m_SimContext = NULL; } }
void HierarchicalPathfinder::Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid) { PROFILE3("Hierarchical Update"); for (int cj = 0; cj < m_ChunksH; ++cj) { for (int ci = 0; ci < m_ChunksW; ++ci) { if (!IsChunkDirty(ci, cj, dirtinessGrid)) continue; for (const std::pair<std::string, pass_class_t>& passClassMask : m_PassClassMasks) { pass_class_t passClass = passClassMask.second; Chunk& a = m_Chunks[passClass].at(ci + cj*m_ChunksW); a.InitRegions(ci, cj, grid, passClass); } } } // TODO: Also be clever with edges m_Edges.clear(); for (const std::pair<std::string, pass_class_t>& passClassMask : m_PassClassMasks) { pass_class_t passClass = passClassMask.second; EdgesMap& edges = m_Edges[passClass]; for (int cj = 0; cj < m_ChunksH; ++cj) { for (int ci = 0; ci < m_ChunksW; ++ci) { FindEdges(ci, cj, passClass, edges); } } } if (m_DebugOverlay) { PROFILE("debug overlay"); m_DebugOverlayLines.clear(); AddDebugEdges(GetPassabilityClass("default")); } }