Planeshift

walkpoly.h

Go to the documentation of this file.
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