Planeshift
walkpoly.h
Go to the documentation of this file.
1 /*
2 * walkpoly.h
3 *
4 * Copyright (C) 2005 Atomic Blue (info@planeshift.it, http://www.atomicblue.org)
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation (version 2
9 * of the License).
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 
19 #ifndef ___WALKPOLY_HEADER___
20 #define ___WALKPOLY_HEADER___
21 #if USE_WALKPOLY
22 //=============================================================================
23 // Crystal Space Includes
24 //=============================================================================
25 #include <csgeom/vector3.h>
26 #include <csgeom/box.h>
27 #include <iutil/objreg.h>
28 #include <csutil/array.h>
29 #include <csutil/csstring.h>
30 #include <csutil/list.h>
31 
32 //=============================================================================
33 // Local Includes
34 //=============================================================================
35 #include "pathfind.h"
36 
41 class psNPCClient;
42 
43 void Dump3(const char* name, const csVector3 &p);
44 void Dump(const char* name, const csBox3 &b);
45 void Dump(const char* name, const csVector3 &p);
46 
47 float Calc2DDistance(const csVector3 &a, const csVector3 &b);
48 float AngleDiff(float a1, float a2);
49 
51 class ps2DLine
52 {
53 public:
54  float a, b, c;
55 
56  void Dump();
57  void Calc(const csVector3 &p1, const csVector3 &p2);
58  void CalcPerp(const csVector3 &begin, const csVector3 &end);
59  float CalcDist(const csVector3 &point);
60  float CalcRel(const csVector3 &point);
61  void Copy(ps2DLine &dest);
62 };
63 
64 class psWalkPoly;
65 class psMapWalker;
66 
67 struct iSector;
68 class CelBase;
69 struct iDocumentNode;
70 struct iVFS;
71 
72 /**************************************************************************
73 * psSpatialIndex is a tree-style data structure.
74 * Its purpose is fast search of the psWalkPoly that is under your feet
75 * or close to you.
76 * It recursively splits the space into pairs of rectangular subspaces.
77 *
78 * Each subspace corresponds to one node of the tree.
79 * Each node keeps list of psWalkPolys whose psWalkPoly::box
80 * collides with the subspace of the node.
81 ***************************************************************************/
82 
83 class psSpatialIndexNode
84 {
85  friend class psSpatialIndex;
86 public:
87  psSpatialIndexNode();
88 
91  psSpatialIndexNode* FindNodeOfPoint(const csVector3 &p);
92 
94  void Add(psWalkPoly* poly);
95 
96  csBox3 &GetBBox()
97  {
98  return bbox;
99  }
100 
101  csList<psWalkPoly*>* GetPolys()
102  {
103  return &polys;
104  };
105 
106 protected:
107 
109  int GetTreeLevel();
110 
112  void Split();
113 
115  void ChooseSplit();
116 
117  psSpatialIndexNode* child1, * child2;
118  psSpatialIndexNode* parent;
119 
120  csBox3 bbox;
122  float splitValue;
124  char splitAxis;
126  csList<psWalkPoly*> polys;
127  int numPolys;
128 };
129 
130 class psSpatialIndex
131 {
132 public:
133 
134  psSpatialIndex();
135 
137  void Add(psWalkPoly* poly);
138 
140  void Rebuild();
141 
144  psSpatialIndexNode* FindNodeOfPoint(const csVector3 &p, psSpatialIndexNode* hint=NULL);
145 
146  //psSpatialIndexNode * FindNodeOfPoly(psWalkPoly * poly);
147 
150  psWalkPoly* FindPolyOfPoint(const csVector3 &p, psSpatialIndexNode* hint=NULL);
151 
152  psANode* FindNearbyANode(const csVector3 &pos);
153 
154 protected:
155  psSpatialIndexNode root;
156 };
157 
158 class psSeed
159 {
160 public:
161  psSeed();
162  psSeed(csVector3 pos, iSector* sector, float quality);
163  psSeed(csVector3 edgePos, csVector3 pos, iSector* sector, float quality);
164  void SaveToString(csString &str);
165  void LoadFromXML(iDocumentNode* node, iEngine* engine);
166  bool CheckValidity(psMapWalker* walker);
167 
168  bool edgeSeed;
169  float quality;
170  csVector3 pos, edgePos;
171  iSector* sector;
172 };
173 
174 class psSeedSet
175 {
176 public:
177  psSeedSet(iObjectRegistry* objReg);
178  psSeed PickUpBestSeed();
179  void AddSeed(const psSeed &seed);
180  bool IsEmpty()
181  {
182  return seeds.IsEmpty();
183  }
184 
185  bool LoadFromString(const csString &str);
186  bool LoadFromFile(const csString &path);
187 
188  void SaveToString(csString &str);
189  bool SaveToFile(const csString &path);
190 
191 protected:
192  iObjectRegistry* objReg;
193  csList<psSeed> seeds;
194 };
195 
196 /*****************************************************************
197 * The areas of map that are without major obstacles are denoted
198 * by set of polygons that cover these areas. This is used
199 * to precisely calculate very short paths. Other paths
200 * are calculated using A*, and later fine-tuned with this map.
201 ******************************************************************/
202 
204 class psWalkPolyCont
205 {
206 public:
207  csVector3 begin, end;
208  psWalkPoly* poly;
209 };
210 
213 class psWalkPolyVert
214 {
215 public:
216  csVector3 pos;
217  ps2DLine line;
218  csArray<psWalkPolyCont> conts;
219  csString info;
220 
221  bool touching, stuck;
222  bool followingEdge;
223 
224  float angle;
225 
226  psWalkPolyVert();
227  psWalkPolyVert(const csVector3 &pos);
228 
231  psWalkPoly* FindCont(const csVector3 &point);
232 
233  void CalcLineTo(const csVector3 &point);
234 };
235 
237 class psWalkPolyMap
238 {
239  friend class psWalkPoly;
240 public:
241  psWalkPolyMap(iObjectRegistry* objReg);
242  psWalkPolyMap();
243 
244  void SetObjReg(iObjectRegistry* objReg)
245  {
246  this->objReg=objReg;
247  }
248 
250  void AddPoly(psWalkPoly*);
251 
253  bool CheckDirectPath(csVector3 start, csVector3 goal);
254 
255  void Generate(psNPCClient* npcclient, psSeedSet &seeds, iSector* sector);
256 
257  void CalcConts();
258 
259  csString DumpPolys();
260 
261  void BuildBasicAMap(psAMap &AMap);
262 
263  void LoadFromXML(iDocumentNode* node);
264  bool LoadFromString(const csString &str);
265  bool LoadFromFile(const csString &path);
266 
267  void SaveToString(csString &str);
268  bool SaveToFile(const csString &path);
269 
270  psANode* FindNearbyANode(const csVector3 &pos);
271 
272  psWalkPoly* FindPoly(int id);
273 
274  void PrunePolys();
275 
276  void DeleteContsWith(psWalkPoly* poly);
277 
278 protected:
279 
280  csList<psWalkPoly*> polys;
281  psSpatialIndex index;
282 
283  csHash<psWalkPoly*> polyByID;
284 
285  iObjectRegistry* objReg;
286  csRef<iVFS> vfs;
287 };
288 
289 /********************************************************************
290  * A convex polygon that denotes area without major obstacles .
291  * It is not necessarily a real polygon, because its vertices
292  * do not have to be on the same 3D plane (just "roughly").
293  * The walkable area within the polygon borders is rarely flat, too.
294  ********************************************************************/
295 
296 class psWalkPoly
297 {
298  friend class psWalkPolyMap;
299 public:
300  psWalkPoly();
301  ~psWalkPoly();
302 
305  void AddVert(const csVector3 &pos, int beforeIndex=-1);
306  size_t GetNumVerts()
307  {
308  return verts.GetSize();
309  }
310 
311  void AddNode(psANode* node);
312  void DeleteNode(psANode* node);
313 
314  void SetSector(iSector* sector);
315 
316 
320  bool MoveToNextPoly(const csVector3 &goal, csVector3 &point, psWalkPoly* &nextPoly);
321 
322  void AddSeeds(psMapWalker* walker, psSeedSet &seeds);
323 
325  bool CheckConvexity(int vertNum);
326 
327  void Clear();
328 
329  //ignores y
330  void Cut(const csVector3 &cut1, const csVector3 &cut2);
331  //ignores y
332  void Intersect(const psWalkPoly &other);
333 
334  float EstimateY(const csVector3 &point);
335 
336  void Dump(const char* name);
337  void DumpJS(const char* name);
338  void DumpPureJS();
339  void DumpPolyJS(const char* name);
340 
341  int Stretch(psMapWalker &walker, psWalkPolyMap &map, float stepSize);
342  void GlueToNeighbours(psMapWalker &walker, psWalkPolyMap &map);
343 
344  float GetBoxSize();
345  float GetArea();
346  float GetTriangleArea(int vertNum);
347  float GetLengthOfEdges();
348  void GetShape(float &min, float &max);
349  float GetNarrowness();
350 
351  void PruneUnboundVerts(psMapWalker &walker);
352  void PruneInLineVerts();
353 
354  bool IsNearWalls(psMapWalker &walker, int vertNum);
355 
357  bool StretchVert(psMapWalker &walker, psWalkPolyMap &map, int vertNum, const csVector3 &newPos, float stepSize);
358 
359  void SetMini(psMapWalker &walker, const csVector3 &pos, int numVerts);
360 
362  void CalcBox();
363  csBox3 &GetBox()
364  {
365  return box;
366  }
367 
368  bool IsInLine();
369 
370  void ClearInfo();
371 
372  bool CollidesWithPolys(psWalkPolyMap &map, csList<psWalkPoly*>* polys);
373 
374  void SaveToString(csString &str);
375  void LoadFromXML(iDocumentNode* node, iEngine* engine);
376 
378  void CalcConts(psWalkPolyMap &map);
379 
380  void RecalcAllEdges();
381 
382  void ConnectNodeToPoly(psANode* node, bool bidirectional);
383 
384  bool TouchesPoly(psWalkPoly* poly);
385  bool NeighboursTouchEachOther();
386 
387  psANode* GetFirstNode();
388 
389  int GetID()
390  {
391  return id;
392  }
393  iSector* GetSector()
394  {
395  return sector;
396  }
397 
398  bool PointIsIn(const csVector3 &p, float maxRel=0);
399 
400  csVector3 GetClosestPoint(const csVector3 &point, float &angle);
401 
402  int GetNumConts();
403 
404  size_t GetNumNodes()
405  {
406  return nodes.GetSize();
407  }
408 
409  bool ReachableFromNeighbours();
410 
411  psWalkPoly* GetNearNeighbour(const csVector3 &pos, float maxDist);
412 
413  void DeleteContsWith(psWalkPoly* poly);
414 
415  bool NeighbourSupsMe(psWalkPoly* neighbour);
416 
417  void MovePointInside(csVector3 &point, const csVector3 &goal);
418 
419 protected:
420 
421  void RecalcEdges(int vertNum);
422 
423  int FindClosestEdge(const csVector3 pos);
424 
427  psWalkPoly* FindCont(const csVector3 &point, int edgeNum);
428 
432  bool MoveToBorder(const csVector3 &goal, csVector3 &point, int &edgeNum);
433 
434 
436  void CalcEdges();
437 
438 
439  int GetNeighbourIndex(int vertNum, int offset) const;
440 
441  bool HandleProblems(psMapWalker &walker, psWalkPolyMap &map, int vertNum, const csVector3 &oldPos);
442  csVector3 GetClosestCollisionPoint(csList<psWalkPoly*> &collisions, ps2DLine &line);
443  bool HandlePolyCollisions(psWalkPolyMap &map, int vertNum, const csVector3 &oldPos);
444 
445  int id;
446  static int nextID;
447  bool supl;
448 
449  csArray<psWalkPolyVert> verts;
450  iSector* sector;
451  csBox3 box;
453  csArray<psANode*> nodes;
454 };
455 
458 #endif
459 
460 #endif
461 
psNPCClient * npcclient
Global connection to the NPC Client.
#define min(x, y)
Definition: xdelta3.h:317
bool CheckValidity(iDocument *musicalScore, csRef< iDocumentNode > &partNode)
Checks if the given document is a valid musical score and provide the <part> node.
The main NPC Client class holding references to important superclient objects.
Definition: npcclient.h:81
#define max(x, y)
Definition: xdelta3.h:314
void Split(const csString &str, csArray< csString > &arr)
Split a csString into an array of sctrings.