Pyrogenesis  trunk
HierarchicalPathfinder.h
Go to the documentation of this file.
1 /* Copyright (C) 2015 Wildfire Games.
2  * This file is part of 0 A.D.
3  *
4  * 0 A.D. is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 2 of the License, or
7  * (at your option) any later version.
8  *
9  * 0 A.D. is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16  */
17 
18 #ifndef INCLUDED_HIERPATHFINDER
19 #define INCLUDED_HIERPATHFINDER
20 
21 #include "Pathfinding.h"
22 
24 #include "Render.h"
25 #include "graphics/SColor.h"
26 
27 /**
28  * Hierarchical pathfinder.
29  *
30  * It doesn't find shortest paths, but deals with connectivity.
31  *
32  * The navcell-grid representation of the map is split into fixed-size chunks.
33  * Within a chunk, each maximal set of adjacently-connected passable navcells
34  * is defined as a region.
35  * Each region is a vertex in the hierarchical pathfinder's graph.
36  * When two regions in adjacent chunks are connected by passable navcells,
37  * the graph contains an edge between the corresponding two vertexes.
38  * (There will never be an edge between two regions in the same chunk.)
39  *
40  * Since regions are typically fairly large, it is possible to determine
41  * connectivity between any two navcells by mapping them onto their appropriate
42  * region and then doing a relatively small graph search.
43  */
44 
46 
48 {
49 public:
50  struct RegionID
51  {
52  u8 ci, cj; // chunk ID
53  u16 r; // unique-per-chunk local region ID
54 
55  RegionID(u8 ci, u8 cj, u16 r) : ci(ci), cj(cj), r(r) { }
56 
57  bool operator<(RegionID b) const
58  {
59  // Sort by chunk ID, then by per-chunk region ID
60  if (ci < b.ci)
61  return true;
62  if (b.ci < ci)
63  return false;
64  if (cj < b.cj)
65  return true;
66  if (b.cj < cj)
67  return false;
68  return r < b.r;
69  }
70 
71  bool operator==(RegionID b) const
72  {
73  return ((ci == b.ci) && (cj == b.cj) && (r == b.r));
74  }
75  };
76 
79 
80  void SetDebugOverlay(bool enabled, const CSimContext* simContext);
81 
82  // Non-pathfinding grids will never be recomputed on calling HierarchicalPathfinder::Update
83  void Recompute(Grid<NavcellData>* passabilityGrid,
84  const std::map<std::string, pass_class_t>& nonPathfindingPassClassMasks,
85  const std::map<std::string, pass_class_t>& pathfindingPassClassMasks);
86 
87  void Update(Grid<NavcellData>* grid, const Grid<u8>& dirtinessGrid);
88 
89  bool IsChunkDirty(int ci, int cj, const Grid<u8>& dirtinessGrid) const;
90 
91  RegionID Get(u16 i, u16 j, pass_class_t passClass);
92 
93  /**
94  * Updates @p goal so that it's guaranteed to be reachable from the navcell
95  * @p i0, @p j0 (which is assumed to be on a passable navcell).
96  *
97  * If the goal is not reachable, it is replaced with a point goal nearest to
98  * the goal center.
99  *
100  * In the case of a non-point reachable goal, it is replaced with a point goal
101  * at the reachable navcell of the goal which is nearest to the starting navcell.
102  */
103  void MakeGoalReachable(u16 i0, u16 j0, PathGoal& goal, pass_class_t passClass);
104 
105  /**
106  * Updates @p i, @p j (which is assumed to be an impassable navcell)
107  * to the nearest passable navcell.
108  */
109  void FindNearestPassableNavcell(u16& i, u16& j, pass_class_t passClass);
110 
111  /**
112  * Generates the connectivity grid associated with the given pass_class
113  */
115 
116  pass_class_t GetPassabilityClass(const std::string& name) const
117  {
118  auto it = m_PassClassMasks.find(name);
119  if (it != m_PassClassMasks.end())
120  return it->second;
121 
122  LOGERROR("Invalid passability class name '%s'", name.c_str());
123  return 0;
124  }
125 
126 private:
127  static const u8 CHUNK_SIZE = 96; // number of navcells per side
128  // TODO PATHFINDER: figure out best number. Probably 64 < n < 128
129 
130  struct Chunk
131  {
132  u8 m_ChunkI, m_ChunkJ; // chunk ID
133  u16 m_NumRegions; // number of local region IDs (starting from 1)
134  u16 m_Regions[CHUNK_SIZE][CHUNK_SIZE]; // local region ID per navcell
135 
136  cassert(CHUNK_SIZE*CHUNK_SIZE/2 < 65536); // otherwise we could overflow m_NumRegions with a checkerboard pattern
137 
138  void InitRegions(int ci, int cj, Grid<NavcellData>* grid, pass_class_t passClass);
139 
140  RegionID Get(int i, int j) const;
141 
142  void RegionCenter(u16 r, int& i, int& j) const;
143 
144  void RegionNavcellNearest(u16 r, int iGoal, int jGoal, int& iBest, int& jBest, u32& dist2Best) const;
145 
146  bool RegionNearestNavcellInGoal(u16 r, u16 i0, u16 j0, const PathGoal& goal, u16& iOut, u16& jOut, u32& dist2Best) const;
147  };
148 
149  typedef std::map<RegionID, std::set<RegionID> > EdgesMap;
150 
151  void FindEdges(u8 ci, u8 cj, pass_class_t passClass, EdgesMap& edges);
152 
153  void FindReachableRegions(RegionID from, std::set<RegionID>& reachable, pass_class_t passClass);
154 
155  void FindPassableRegions(std::set<RegionID>& regions, pass_class_t passClass);
156 
157  /**
158  * Updates @p iGoal and @p jGoal to the navcell that is the nearest to the
159  * initial goal coordinates, in one of the given @p regions.
160  * (Assumes @p regions is non-empty.)
161  */
162  void FindNearestNavcellInRegions(const std::set<RegionID>& regions, u16& iGoal, u16& jGoal, pass_class_t passClass);
163 
164  Chunk& GetChunk(u8 ci, u8 cj, pass_class_t passClass)
165  {
166  return m_Chunks[passClass].at(cj * m_ChunksW + ci);
167  }
168 
169  void FillRegionOnGrid(const RegionID& region, pass_class_t passClass, u16 value, Grid<u16>& grid);
170 
173  std::map<pass_class_t, std::vector<Chunk> > m_Chunks;
174 
175  std::map<pass_class_t, EdgesMap> m_Edges;
176 
177  // Passability classes for which grids will be updated when calling Update
178  std::map<std::string, pass_class_t> m_PassClassMasks;
179 
180  void AddDebugEdges(pass_class_t passClass);
182  const CSimContext* m_SimContext; // Used for drawing the debug lines
183 
184 public:
185  std::vector<SOverlayLine> m_DebugOverlayLines;
186 };
187 
189 {
190 public:
192 
194  TerrainTextureOverlay(Pathfinding::NAVCELLS_PER_TILE), m_PathfinderHier(pathfinderHier)
195  {
196  }
197 
198  virtual void BuildTextureRGBA(u8* data, size_t w, size_t h)
199  {
200  pass_class_t passClass = m_PathfinderHier.GetPassabilityClass("default");
201 
202  for (size_t j = 0; j < h; ++j)
203  {
204  for (size_t i = 0; i < w; ++i)
205  {
206  SColor4ub color;
207 
208  HierarchicalPathfinder::RegionID rid = m_PathfinderHier.Get(i, j, passClass);
209  if (rid.r == 0)
210  color = SColor4ub(0, 0, 0, 0);
211  else if (rid.r == 0xFFFF)
212  color = SColor4ub(255, 0, 255, 255);
213  else
214  color = GetColor(rid.r + rid.ci*5 + rid.cj*7, 127);
215 
216  *data++ = color.R;
217  *data++ = color.G;
218  *data++ = color.B;
219  *data++ = color.A;
220  }
221  }
222  }
223 };
224 
225 
226 #endif // INCLUDED_HIERPATHFINDER
Definition: HierarchicalPathfinder.h:130
u8 G
Definition: SColor.h:33
HierarchicalOverlay * m_DebugOverlay
Definition: HierarchicalPathfinder.h:181
#define LOGERROR(...)
Definition: CLogger.h:36
u16 pass_class_t
Definition: Pathfinding.h:29
u16 m_ChunksH
Definition: HierarchicalPathfinder.h:172
Definition: Pathfinding.h:105
RegionID(u8 ci, u8 cj, u16 r)
Definition: HierarchicalPathfinder.h:55
void Update(Grid< NavcellData > *grid, const Grid< u8 > &dirtinessGrid)
Definition: HierarchicalPathfinder.cpp:404
HierarchicalOverlay(HierarchicalPathfinder &pathfinderHier)
Definition: HierarchicalPathfinder.h:193
uint16_t u16
Definition: types.h:38
Grid< u16 > GetConnectivityGrid(pass_class_t passClass)
Generates the connectivity grid associated with the given pass_class.
Definition: HierarchicalPathfinder.cpp:755
u16 m_W
Definition: HierarchicalPathfinder.h:171
Chunk & GetChunk(u8 ci, u8 cj, pass_class_t passClass)
Definition: HierarchicalPathfinder.h:164
Pathfinder goal.
Definition: PathGoal.h:32
void Recompute(Grid< NavcellData > *passabilityGrid, const std::map< std::string, pass_class_t > &nonPathfindingPassClassMasks, const std::map< std::string, pass_class_t > &pathfindingPassClassMasks)
Definition: HierarchicalPathfinder.cpp:346
Contains pointers to various &#39;global&#39; objects that are needed by the simulation code, to allow easy access without using real (evil) global variables.
Definition: SimContext.h:32
u8 B
Definition: SColor.h:34
uint8_t u8
Definition: types.h:37
bool operator<(RegionID b) const
Definition: HierarchicalPathfinder.h:57
u16 m_NumRegions
Definition: HierarchicalPathfinder.h:133
u8 m_ChunkJ
Definition: HierarchicalPathfinder.h:132
u8 A
Definition: SColor.h:35
void FindPassableRegions(std::set< RegionID > &regions, pass_class_t passClass)
Definition: HierarchicalPathfinder.cpp:729
Definition: HierarchicalPathfinder.h:188
u8 cj
Definition: HierarchicalPathfinder.h:52
RegionID Get(u16 i, u16 j, pass_class_t passClass)
Definition: HierarchicalPathfinder.cpp:566
HierarchicalPathfinder()
Definition: HierarchicalPathfinder.cpp:320
uint32_t u32
Definition: types.h:39
const int NAVCELLS_PER_TILE
The long-range pathfinder operates primarily over a navigation grid (a uniform-cost 2D passability gr...
Definition: Pathfinding.h:117
void FindNearestPassableNavcell(u16 &i, u16 &j, pass_class_t passClass)
Updates i, j (which is assumed to be an impassable navcell) to the nearest passable navcell...
Definition: HierarchicalPathfinder.cpp:643
Definition: HierarchicalPathfinder.h:47
Definition: HierarchicalPathfinder.h:50
Definition: SColor.h:30
~HierarchicalPathfinder()
Definition: HierarchicalPathfinder.cpp:324
HierarchicalPathfinder & m_PathfinderHier
Definition: HierarchicalPathfinder.h:191
void SetDebugOverlay(bool enabled, const CSimContext *simContext)
Definition: HierarchicalPathfinder.cpp:329
pass_class_t GetPassabilityClass(const std::string &name) const
Definition: HierarchicalPathfinder.h:116
u8 R
Definition: SColor.h:32
u8 ci
Definition: HierarchicalPathfinder.h:52
void FindReachableRegions(RegionID from, std::set< RegionID > &reachable, pass_class_t passClass)
Definition: HierarchicalPathfinder.cpp:707
Helper functions related to rendering.
void AddDebugEdges(pass_class_t passClass)
Debug visualisation of graph edges between regions.
Definition: HierarchicalPathfinder.cpp:528
void FindEdges(u8 ci, u8 cj, pass_class_t passClass, EdgesMap &edges)
Find edges between regions in this chunk and the adjacent below/left chunks.
Definition: HierarchicalPathfinder.cpp:467
void FindNearestNavcellInRegions(const std::set< RegionID > &regions, u16 &iGoal, u16 &jGoal, pass_class_t passClass)
Updates iGoal and jGoal to the navcell that is the nearest to the initial goal coordinates, in one of the given regions.
Definition: HierarchicalPathfinder.cpp:650
u16 m_ChunksW
Definition: HierarchicalPathfinder.h:172
bool IsChunkDirty(int ci, int cj, const Grid< u8 > &dirtinessGrid) const
Definition: HierarchicalPathfinder.cpp:447
void MakeGoalReachable(u16 i0, u16 j0, PathGoal &goal, pass_class_t passClass)
Updates goal so that it&#39;s guaranteed to be reachable from the navcell i0, j0 (which is assumed to be ...
Definition: HierarchicalPathfinder.cpp:574
std::map< std::string, pass_class_t > m_PassClassMasks
Definition: HierarchicalPathfinder.h:178
Base class for texture-based terrain overlays, with an arbitrary number of texels per terrain tile...
Definition: TerrainOverlay.h:174
void FillRegionOnGrid(const RegionID &region, pass_class_t passClass, u16 value, Grid< u16 > &grid)
Definition: HierarchicalPathfinder.cpp:740
virtual void BuildTextureRGBA(u8 *data, size_t w, size_t h)
Called each frame to generate the texture to render on the terrain.
Definition: HierarchicalPathfinder.h:198
u16 m_H
Definition: HierarchicalPathfinder.h:171
std::map< pass_class_t, std::vector< Chunk > > m_Chunks
Definition: HierarchicalPathfinder.h:173
#define cassert(expr)
Compile-time assertion.
Definition: code_annotation.h:197
const CSimContext * m_SimContext
Definition: HierarchicalPathfinder.h:182
std::map< RegionID, std::set< RegionID > > EdgesMap
Definition: HierarchicalPathfinder.h:149
static const u8 CHUNK_SIZE
Definition: HierarchicalPathfinder.h:127
bool operator==(RegionID b) const
Definition: HierarchicalPathfinder.h:71
u16 r
Definition: HierarchicalPathfinder.h:53
std::vector< SOverlayLine > m_DebugOverlayLines
Definition: HierarchicalPathfinder.h:185
std::map< pass_class_t, EdgesMap > m_Edges
Definition: HierarchicalPathfinder.h:175