Planeshift
|
00001 /* 00002 * walkpoly.h 00003 * 00004 * Copyright (C) 2005 Atomic Blue ([email protected], http://www.atomicblue.org) 00005 * 00006 * This program is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU General Public License 00008 * as published by the Free Software Foundation (version 2 00009 * of the License). 00010 * This program is distributed in the hope that it will be useful, 00011 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 * GNU General Public License for more details. 00014 * You should have received a copy of the GNU General Public License 00015 * along with this program; if not, write to the Free Software 00016 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00017 */ 00018 00019 #ifndef ___WALKPOLY_HEADER___ 00020 #define ___WALKPOLY_HEADER___ 00021 #if USE_WALKPOLY 00022 //============================================================================= 00023 // Crystal Space Includes 00024 //============================================================================= 00025 #include <csgeom/vector3.h> 00026 #include <csgeom/box.h> 00027 #include <iutil/objreg.h> 00028 #include <csutil/array.h> 00029 #include <csutil/csstring.h> 00030 #include <csutil/list.h> 00031 00032 //============================================================================= 00033 // Local Includes 00034 //============================================================================= 00035 #include "pathfind.h" 00036 00041 class psNPCClient; 00042 00043 void Dump3(const char* name, const csVector3 &p); 00044 void Dump(const char* name, const csBox3 &b); 00045 void Dump(const char* name, const csVector3 &p); 00046 00047 float Calc2DDistance(const csVector3 &a, const csVector3 &b); 00048 float AngleDiff(float a1, float a2); 00049 00051 class ps2DLine 00052 { 00053 public: 00054 float a, b, c; 00055 00056 void Dump(); 00057 void Calc(const csVector3 &p1, const csVector3 &p2); 00058 void CalcPerp(const csVector3 &begin, const csVector3 &end); 00059 float CalcDist(const csVector3 &point); 00060 float CalcRel(const csVector3 &point); 00061 void Copy(ps2DLine &dest); 00062 }; 00063 00064 class psWalkPoly; 00065 class psMapWalker; 00066 00067 struct iSector; 00068 class CelBase; 00069 struct iDocumentNode; 00070 struct iVFS; 00071 00072 /************************************************************************** 00073 * psSpatialIndex is a tree-style data structure. 00074 * Its purpose is fast search of the psWalkPoly that is under your feet 00075 * or close to you. 00076 * It recursively splits the space into pairs of rectangular subspaces. 00077 * 00078 * Each subspace corresponds to one node of the tree. 00079 * Each node keeps list of psWalkPolys whose psWalkPoly::box 00080 * collides with the subspace of the node. 00081 ***************************************************************************/ 00082 00083 class psSpatialIndexNode 00084 { 00085 friend class psSpatialIndex; 00086 public: 00087 psSpatialIndexNode(); 00088 00091 psSpatialIndexNode* FindNodeOfPoint(const csVector3 &p); 00092 00094 void Add(psWalkPoly* poly); 00095 00096 csBox3 &GetBBox() 00097 { 00098 return bbox; 00099 } 00100 00101 csList<psWalkPoly*>* GetPolys() 00102 { 00103 return &polys; 00104 }; 00105 00106 protected: 00107 00109 int GetTreeLevel(); 00110 00112 void Split(); 00113 00115 void ChooseSplit(); 00116 00117 psSpatialIndexNode* child1, * child2; 00118 psSpatialIndexNode* parent; 00119 00120 csBox3 bbox; 00122 float splitValue; 00124 char splitAxis; 00126 csList<psWalkPoly*> polys; 00127 int numPolys; 00128 }; 00129 00130 class psSpatialIndex 00131 { 00132 public: 00133 00134 psSpatialIndex(); 00135 00137 void Add(psWalkPoly* poly); 00138 00140 void Rebuild(); 00141 00144 psSpatialIndexNode* FindNodeOfPoint(const csVector3 &p, psSpatialIndexNode* hint=NULL); 00145 00146 //psSpatialIndexNode * FindNodeOfPoly(psWalkPoly * poly); 00147 00150 psWalkPoly* FindPolyOfPoint(const csVector3 &p, psSpatialIndexNode* hint=NULL); 00151 00152 psANode* FindNearbyANode(const csVector3 &pos); 00153 00154 protected: 00155 psSpatialIndexNode root; 00156 }; 00157 00158 class psSeed 00159 { 00160 public: 00161 psSeed(); 00162 psSeed(csVector3 pos, iSector* sector, float quality); 00163 psSeed(csVector3 edgePos, csVector3 pos, iSector* sector, float quality); 00164 void SaveToString(csString &str); 00165 void LoadFromXML(iDocumentNode* node, iEngine* engine); 00166 bool CheckValidity(psMapWalker* walker); 00167 00168 bool edgeSeed; 00169 float quality; 00170 csVector3 pos, edgePos; 00171 iSector* sector; 00172 }; 00173 00174 class psSeedSet 00175 { 00176 public: 00177 psSeedSet(iObjectRegistry* objReg); 00178 psSeed PickUpBestSeed(); 00179 void AddSeed(const psSeed &seed); 00180 bool IsEmpty() 00181 { 00182 return seeds.IsEmpty(); 00183 } 00184 00185 bool LoadFromString(const csString &str); 00186 bool LoadFromFile(const csString &path); 00187 00188 void SaveToString(csString &str); 00189 bool SaveToFile(const csString &path); 00190 00191 protected: 00192 iObjectRegistry* objReg; 00193 csList<psSeed> seeds; 00194 }; 00195 00196 /***************************************************************** 00197 * The areas of map that are without major obstacles are denoted 00198 * by set of polygons that cover these areas. This is used 00199 * to precisely calculate very short paths. Other paths 00200 * are calculated using A*, and later fine-tuned with this map. 00201 ******************************************************************/ 00202 00204 class psWalkPolyCont 00205 { 00206 public: 00207 csVector3 begin, end; 00208 psWalkPoly* poly; 00209 }; 00210 00213 class psWalkPolyVert 00214 { 00215 public: 00216 csVector3 pos; 00217 ps2DLine line; 00218 csArray<psWalkPolyCont> conts; 00219 csString info; 00220 00221 bool touching, stuck; 00222 bool followingEdge; 00223 00224 float angle; 00225 00226 psWalkPolyVert(); 00227 psWalkPolyVert(const csVector3 &pos); 00228 00231 psWalkPoly* FindCont(const csVector3 &point); 00232 00233 void CalcLineTo(const csVector3 &point); 00234 }; 00235 00237 class psWalkPolyMap 00238 { 00239 friend class psWalkPoly; 00240 public: 00241 psWalkPolyMap(iObjectRegistry* objReg); 00242 psWalkPolyMap(); 00243 00244 void SetObjReg(iObjectRegistry* objReg) 00245 { 00246 this->objReg=objReg; 00247 } 00248 00250 void AddPoly(psWalkPoly*); 00251 00253 bool CheckDirectPath(csVector3 start, csVector3 goal); 00254 00255 void Generate(psNPCClient* npcclient, psSeedSet &seeds, iSector* sector); 00256 00257 void CalcConts(); 00258 00259 csString DumpPolys(); 00260 00261 void BuildBasicAMap(psAMap &AMap); 00262 00263 void LoadFromXML(iDocumentNode* node); 00264 bool LoadFromString(const csString &str); 00265 bool LoadFromFile(const csString &path); 00266 00267 void SaveToString(csString &str); 00268 bool SaveToFile(const csString &path); 00269 00270 psANode* FindNearbyANode(const csVector3 &pos); 00271 00272 psWalkPoly* FindPoly(int id); 00273 00274 void PrunePolys(); 00275 00276 void DeleteContsWith(psWalkPoly* poly); 00277 00278 protected: 00279 00280 csList<psWalkPoly*> polys; 00281 psSpatialIndex index; 00282 00283 csHash<psWalkPoly*> polyByID; 00284 00285 iObjectRegistry* objReg; 00286 csRef<iVFS> vfs; 00287 }; 00288 00289 /******************************************************************** 00290 * A convex polygon that denotes area without major obstacles . 00291 * It is not necessarily a real polygon, because its vertices 00292 * do not have to be on the same 3D plane (just "roughly"). 00293 * The walkable area within the polygon borders is rarely flat, too. 00294 ********************************************************************/ 00295 00296 class psWalkPoly 00297 { 00298 friend class psWalkPolyMap; 00299 public: 00300 psWalkPoly(); 00301 ~psWalkPoly(); 00302 00305 void AddVert(const csVector3 &pos, int beforeIndex=-1); 00306 size_t GetNumVerts() 00307 { 00308 return verts.GetSize(); 00309 } 00310 00311 void AddNode(psANode* node); 00312 void DeleteNode(psANode* node); 00313 00314 void SetSector(iSector* sector); 00315 00316 00320 bool MoveToNextPoly(const csVector3 &goal, csVector3 &point, psWalkPoly* &nextPoly); 00321 00322 void AddSeeds(psMapWalker* walker, psSeedSet &seeds); 00323 00325 bool CheckConvexity(int vertNum); 00326 00327 void Clear(); 00328 00329 //ignores y 00330 void Cut(const csVector3 &cut1, const csVector3 &cut2); 00331 //ignores y 00332 void Intersect(const psWalkPoly &other); 00333 00334 float EstimateY(const csVector3 &point); 00335 00336 void Dump(const char* name); 00337 void DumpJS(const char* name); 00338 void DumpPureJS(); 00339 void DumpPolyJS(const char* name); 00340 00341 int Stretch(psMapWalker &walker, psWalkPolyMap &map, float stepSize); 00342 void GlueToNeighbours(psMapWalker &walker, psWalkPolyMap &map); 00343 00344 float GetBoxSize(); 00345 float GetArea(); 00346 float GetTriangleArea(int vertNum); 00347 float GetLengthOfEdges(); 00348 void GetShape(float &min, float &max); 00349 float GetNarrowness(); 00350 00351 void PruneUnboundVerts(psMapWalker &walker); 00352 void PruneInLineVerts(); 00353 00354 bool IsNearWalls(psMapWalker &walker, int vertNum); 00355 00357 bool StretchVert(psMapWalker &walker, psWalkPolyMap &map, int vertNum, const csVector3 &newPos, float stepSize); 00358 00359 void SetMini(psMapWalker &walker, const csVector3 &pos, int numVerts); 00360 00362 void CalcBox(); 00363 csBox3 &GetBox() 00364 { 00365 return box; 00366 } 00367 00368 bool IsInLine(); 00369 00370 void ClearInfo(); 00371 00372 bool CollidesWithPolys(psWalkPolyMap &map, csList<psWalkPoly*>* polys); 00373 00374 void SaveToString(csString &str); 00375 void LoadFromXML(iDocumentNode* node, iEngine* engine); 00376 00378 void CalcConts(psWalkPolyMap &map); 00379 00380 void RecalcAllEdges(); 00381 00382 void ConnectNodeToPoly(psANode* node, bool bidirectional); 00383 00384 bool TouchesPoly(psWalkPoly* poly); 00385 bool NeighboursTouchEachOther(); 00386 00387 psANode* GetFirstNode(); 00388 00389 int GetID() 00390 { 00391 return id; 00392 } 00393 iSector* GetSector() 00394 { 00395 return sector; 00396 } 00397 00398 bool PointIsIn(const csVector3 &p, float maxRel=0); 00399 00400 csVector3 GetClosestPoint(const csVector3 &point, float &angle); 00401 00402 int GetNumConts(); 00403 00404 size_t GetNumNodes() 00405 { 00406 return nodes.GetSize(); 00407 } 00408 00409 bool ReachableFromNeighbours(); 00410 00411 psWalkPoly* GetNearNeighbour(const csVector3 &pos, float maxDist); 00412 00413 void DeleteContsWith(psWalkPoly* poly); 00414 00415 bool NeighbourSupsMe(psWalkPoly* neighbour); 00416 00417 void MovePointInside(csVector3 &point, const csVector3 &goal); 00418 00419 protected: 00420 00421 void RecalcEdges(int vertNum); 00422 00423 int FindClosestEdge(const csVector3 pos); 00424 00427 psWalkPoly* FindCont(const csVector3 &point, int edgeNum); 00428 00432 bool MoveToBorder(const csVector3 &goal, csVector3 &point, int &edgeNum); 00433 00434 00436 void CalcEdges(); 00437 00438 00439 int GetNeighbourIndex(int vertNum, int offset) const; 00440 00441 bool HandleProblems(psMapWalker &walker, psWalkPolyMap &map, int vertNum, const csVector3 &oldPos); 00442 csVector3 GetClosestCollisionPoint(csList<psWalkPoly*> &collisions, ps2DLine &line); 00443 bool HandlePolyCollisions(psWalkPolyMap &map, int vertNum, const csVector3 &oldPos); 00444 00445 int id; 00446 static int nextID; 00447 bool supl; 00448 00449 csArray<psWalkPolyVert> verts; 00450 iSector* sector; 00451 csBox3 box; 00453 csArray<psANode*> nodes; 00454 }; 00455 00458 #endif 00459 00460 #endif 00461