// NeL - MMORPG Framework // Copyright (C) 2010 Winch Gate Property Limited // // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU Affero General Public License as // published by the Free Software Foundation, either version 3 of the // License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU Affero General Public License for more details. // // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . #ifndef NL_LOCAL_RETRIEVER_H #define NL_LOCAL_RETRIEVER_H #include #include #include #include "nel/misc/types_nl.h" #include "nel/misc/vector.h" #include "nel/misc/file.h" #include "nel/misc/aabbox.h" #include "nel/misc/polygon.h" #include "vector_2s.h" #include "surface_quad.h" #include "chain.h" #include "retrievable_surface.h" #include "chain_quad.h" #include "exterior_mesh.h" #include "face_grid.h" #include "nel/pacs/u_global_position.h" namespace NLPACS { class CCollisionSurfaceTemp; /** * A surface retriever, located by its bounding box. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CLocalRetriever { public: /** * A tip of several chains. A CTip can contain more than 2 chains. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CTip { public: /** * A chain tip. Contains the id of the chain and whether this tip is the start of the chain. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ struct CChainTip { /// The id of the chain. sint32 Chain; /// True if this tip is the beginning of the chain. bool Start; /// Constructor. CChainTip(sint32 chainId = 0, bool start = 0) : Chain(chainId), Start(start) {} /// Serielaises the CChainTip void serial(NLMISC::IStream &f) { f.serial(Chain, Start); } }; CTip() : Point(NLMISC::CVector::Null) {} /// The position of the tip.x NLMISC::CVector Point; // The chains linked to that tip. std::vector Chains; public: /// Serialises the CTip. void serial(NLMISC::IStream &f) { f.serial(Point); f.serialCont(Chains); } /// Translates the CTip by the translation vector. void translate(const NLMISC::CVector &translation) { Point += translation; } }; /** * A topology. It's a set of surfaces which are definning a connex master surface. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CTopology : public std::vector { public: void serial(NLMISC::IStream &f) { f.serialCont(*this); } }; /** * An estimation of the position of a point on a specified surface. * The estimated position is LOCAL reference to the retriever axis. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CLocalPosition : public ULocalPosition { public: /// Constructor. CLocalPosition(sint32 surface=-1, const NLMISC::CVector &estimation=NLMISC::CVector::Null) { Surface=surface; Estimation=estimation; } /// Serialises the CLocalPosition. //void serial(NLMISC::IStream &f) { f.serial(Surface, Estimation); } }; /** * The different types of retriever (landscape or interior.) * \author Benjamin Legros * \author Nevrax France * \date 2001 */ enum EType { Landscape = 0, Interior }; /** * The faces used for snapping in interior retrievers. * \author Benjamin Legros * \author Nevrax France * \date 2001 */ class CInteriorFace { public: uint32 Verts[3]; uint32 Surface; public: void serial(NLMISC::IStream &f) { f.serial(Verts[0], Verts[1], Verts[2], Surface); } }; /** * An iterator to go through chains without bothering about ordered chains and those kind of f*cking stuffs * \author Benjamin Legros * \author Nevrax France * \date 2003 */ class CIterator { friend class CLocalRetriever; protected: /// The referent retriever const CLocalRetriever *_Retriever; /// Chain Id uint16 _Chain; /// The current ochain in chain uint16 _OChainIndex; /// The current vertex in ochain sint16 _IndexInOChain; /// Max index in ochain sint16 _MaxIndexInOChain; /// Is ochain forward? bool _OChainForward; public: /// Constructor CIterator(const CLocalRetriever *retriever, uint chain) { _Retriever = retriever; _Chain = uint16(chain); _OChainIndex = 0; setupIndex(); } CIterator &operator ++ () { const CChain &chain = _Retriever->getChain(_Chain); if (_OChainIndex >= chain.getSubChains().size()) return *this; if (_OChainForward) { ++_IndexInOChain; if (((sint)_OChainIndex < (sint)chain.getSubChains().size()-1 && _IndexInOChain == _MaxIndexInOChain) || _IndexInOChain > _MaxIndexInOChain) { ++_OChainIndex; setupIndex(); } } else { --_IndexInOChain; if (((sint)_OChainIndex < (sint)chain.getSubChains().size()-1 && _IndexInOChain == 0) || _IndexInOChain < 0) { ++_OChainIndex; setupIndex(); } } return *this; } CVector2s operator * () const { if (end()) return CVector2s(); return _Retriever->getOrderedChain(_Retriever->getChain(_Chain).getSubChain(_OChainIndex))[_IndexInOChain]; } CVector get3d() const { if (end()) return CVector::Null; return _Retriever->getFullOrderedChain(_Retriever->getChain(_Chain).getSubChain(_OChainIndex))[_IndexInOChain]; } /// Test end bool end() const { return (_OChainIndex >= _Retriever->getChain(_Chain).getSubChains().size()); } private: /// Setup index in ochain void setupIndex() { const CChain &chain = _Retriever->getChain(_Chain); if (_OChainIndex >= chain.getSubChains().size()) return; const COrderedChain &ochain = _Retriever->getOrderedChain(chain.getSubChain(_OChainIndex)); _OChainForward = ochain.isForward(); _MaxIndexInOChain = sint16(ochain.getVertices().size()-1); _IndexInOChain = (_OChainForward ? 0 : _MaxIndexInOChain); } }; protected: friend class CRetrieverInstance; /// The chains insinde the zone. std::vector _OrderedChains; std::vector _FullOrderedChains; /// The chains insinde the zone. std::vector _Chains; /// The surfaces inside the zone. std::vector _Surfaces; /// The bbox of the local retriever NLMISC::CAABBox _BBox; /// The tips making links between different chains. std::vector __Tips; /// The chains on the edges of the zone. std::vector _BorderChains; /// The topologies within the zone. std::vector _Topologies[NumMaxCreatureModels]; /// The tip recognition threshold static const float _TipThreshold; /// The tip recognition threshold static const float _EdgeTipThreshold; /// For collisions, the chainquad. CChainQuad _ChainQuad; /// The type of the retriever EType _Type; /// \name Internior retriever specific // @{ /// The exterior mesh, for collisions CExteriorMesh _ExteriorMesh; /// The vertices of the collision mesh std::vector _InteriorVertices; /// The faces of the collision mesh std::vector _InteriorFaces; /// The face selection grid CFaceGrid _FaceGrid; /// An human readable identifier of the retriever. std::string _Id; // @} /// Tells if retriever is loaded bool _Loaded; public: /// bool LoadCheckFlag; private: /// The intersection between an ordered chain and the path. struct CIntersectionMarker { float Position; uint16 OChain; uint16 Edge; bool In; CIntersectionMarker() {} CIntersectionMarker(float position, uint16 ochain, uint16 edge, bool in) : Position(position), OChain(ochain), Edge(edge), In(in) {} bool operator< (const CIntersectionMarker &comp) const { return Position < comp.Position; } }; public: /// @name Constructors // @{ CLocalRetriever(); // @} /// @name Selectors // @{ /// Returns the chain tips inside the local retrievers. //const std::vector &getTips() const { return _Tips; } /// Returns the nth tip in the retriever. //const CTip &getTip(uint n) const { return _Tips[n]; } /// Returns the ordered chains. const std::vector &getOrderedChains() const { return _OrderedChains; } /// Returns the nth ordered chain. const COrderedChain &getOrderedChain(uint n) const { return _OrderedChains[n]; } /// Returns the full ordered chains. const std::vector &getFullOrderedChains() const { return _FullOrderedChains; } /// Returns the nth full ordered chain. const COrderedChain3f &getFullOrderedChain(uint n) const { return _FullOrderedChains[n]; } /// Returns the chains. const std::vector &getChains() const { return _Chains; } /// retruns the nth chain. const CChain &getChain(uint n) const { return _Chains[n]; } /// Returns the ids of the chains on the edges of the retriever. const std::vector &getBorderChains() const { return _BorderChains; } /// Returns the id of the nth chain on the edges of the retriever. uint16 getBorderChain(uint n) const { return _BorderChains[n]; } /// Returns the surfaces. const std::vector &getSurfaces() const { return _Surfaces; } /// Returns the nth surface. const CRetrievableSurface &getSurface(uint n) const { return _Surfaces[n]; } /// Returns the type of the retriever EType getType() const { return _Type; } /// Returns the bbox const NLMISC::CAABBox &getBBox() const { return _BBox; } /// Returns the exterior mesh of the retriever const CExteriorMesh &getExteriorMesh() const { return _ExteriorMesh; } /// Returns the interior vertices const std::vector &getInteriorVertices() const { return _InteriorVertices; } /// Returns the interior faces const std::vector &getInteriorFaces() const { return _InteriorFaces; } /// Returns the identifier of the retriever. const std::string &getIdentifier() const { return _Id; } /// Is loaded ? bool isLoaded() const { return _Loaded; } /// Force Loaded State. void forceLoaded(bool state) { _Loaded= state; } /// build BBoxes of interior surfaces in surfaceBBoxes (cleared first) void buildInteriorSurfaceBBoxes(std::vector &surfaceBBoxes) const; /// Builds the polygons (loops) of a given surface void buildSurfacePolygons(uint32 surface, std::list &polygons) const; /// Builds the polygons (loops) of all surfaces in the retriever void buildSurfacePolygons(std::list< std::list > &polygons) const { uint i; for (i=0; i<_Surfaces.size(); ++i) { polygons.push_back(std::list()); buildSurfacePolygons(i, polygons.back()); } } /// Builds the polygons (loops) of a given surface void build3dSurfacePolygons(uint32 surface, std::list &polygons) const; /// Builds the polygons (loops) of all surfaces in the retriever void build3dSurfacePolygons(std::list< std::list > &polygons) const { uint i; for (i=0; i<_Surfaces.size(); ++i) { polygons.push_back(std::list()); build3dSurfacePolygons(i, polygons.back()); } } // @} /// @name Mutators //@{ /// Adds a surface to the local retriever, using its features. Returns the id of the newly created surface. sint32 addSurface(uint8 normalq, uint8 orientationq, uint8 mat, uint8 charact, uint8 level, bool isUnderWater, float waterHeight, bool clusterHint, const NLMISC::CVector ¢er, const CSurfaceQuadTree &quad, sint8 quantHeight = 0); /** * Adds a chain to the local retriever, using the vertices of the chain, * the left and right surfaces id and the edge on which the chain is stuck */ sint32 addChain(const std::vector &vertices, sint32 left, sint32 right); /// Set the type of the retriever (see EType) void setType(EType type) { _Type = type; } /// Sets the exterior mesh void setExteriorMesh(const CExteriorMesh &em) { _ExteriorMesh = em; } /// Sets the bbox of the retriever void setBBox(const NLMISC::CAABBox &bbox) { _BBox = bbox; } /// Returns the interior vertices std::vector &getInteriorVertices() { return _InteriorVertices; } /// Returns the interior faces std::vector &getInteriorFaces() { return _InteriorFaces; } /// Returns the identifier of the retriever. void setIdentifier(const std::string &id) { _Id = id; } /// Returns the chain quad CChainQuad &getChainQuad() { return _ChainQuad; } /// Inits the face grid void initFaceGrid(); /// Builds topologies tables. void computeTopologies(); /// Builds tips void computeLoopsAndTips(); /// Found chains on the edges of the retriever and fills _BorderChains tables. void findBorderChains(); /// Updates surfaces links from the links contained in the chains... void updateChainIds(); /// Sorts chains references inside the tips. NOT IMPLEMENTED YET. void sortTips(); /// Translates the local retriever by the translation vector. void translate(const NLMISC::CVector &translation); /// void flushFullOrderedChains() { _FullOrderedChains.clear(); } /// void setFullOrderedChains(const std::vector &foc) { _FullOrderedChains = foc; } /// Serialises the CLocalRetriever. void serial(NLMISC::IStream &f); /// Clear void clear(); // @} /// \name Collisions part. // @{ /// compute the chain quad, used for collisions. the ChainQuad is serialised in serial(). _OrderedChains must be OK. void computeCollisionChainQuad(); /** add possible collisions chains to the temp result. * \param cst the temp result to store collision chains. they are appened to cst.CollisionChains. * \param bboxMove the bbox which bounds the movement of the entity. * \param transBase the vector we use to translate local position of edge. */ void testCollision(CCollisionSurfaceTemp &cst, const NLMISC::CAABBox &bboxMove, const NLMISC::CVector2f &transBase) const; /** * Check all surfaces integrity */ bool checkSurfacesIntegrity(NLMISC::CVector translation = NLMISC::CVector::Null, bool verbose = false) const; /** * Check surface integrity */ bool checkSurfaceIntegrity(uint surf, NLMISC::CVector translation = NLMISC::CVector::Null, bool verbose = false) const; // @} /* protected: */ /// Assures a position is really inside a surface (and independent from any accuracy issue) and returns true if the position was moved. bool insurePosition(ULocalPosition &local) const; /// Retrieves a position inside the retriever (from the local position), returns true if the position is close to a border void retrievePosition(NLMISC::CVector estimated, CCollisionSurfaceTemp &cst) const; /// Retrieves a position inside the retriever (from the local position), returns true if the position is close to a border void retrieveAccuratePosition(CVector2s estimated, CCollisionSurfaceTemp &cst, bool &onBorder) const; /// Retrieves a position inside the retriever (from the local position), returns true if the position is close to a border bool testPosition(ULocalPosition &local, CCollisionSurfaceTemp &cst) const; /// Snaps on the ground void snapToInteriorGround(ULocalPosition &position, bool &snapped) const; /// Get the height of surface that matches the best this position float getHeight(const ULocalPosition &position) const; /// Finds a path in a given surface, from the point A to the point B. void findPath(const CLocalPosition &A, const CLocalPosition &B, std::vector &path, NLPACS::CCollisionSurfaceTemp &cst) const; /// void unify(); /** Get the height of interior surface that matches the best this position. Allows the position to be a bit outside the triangles. * return 0 if not loaded or not an interior surface. * \param outsideTolerance how much are we allowed to look outside the triangles */ float getInteriorHeightAround(const ULocalPosition &position, float outsideTolerance) const; public: // Last minute fix... Some issues appeared when linking (trying to link 2 chains with only 1 in the neighbourhood) class CChainReplacement { public: uint Chain; sint Left, Right; std::vector Vertices; }; // temp object to store replaced ochain ids std::vector FreeOChains; void replaceChain(uint32 chainId, const std::vector &replacement); void forceBorderChainId(uint32 chainId, uint32 borderId) { if (chainId >= _Chains.size()) { nlwarning("forceBorderChainId(): couldn't force border id %d for chain %d, doesn't exist", borderId, chainId); return; } _Chains[chainId].setBorderChainIndex(borderId); } public: const NLMISC::CVector &getStartVector(uint32 chain) const; const NLMISC::CVector &getStopVector(uint32 chain) const; const NLMISC::CVector &getStartVector(uint32 chain, sint32 surface) const; const NLMISC::CVector &getStopVector(uint32 chain, sint32 surface) const; /* uint16 getStartTip(uint32 chain, sint32 surface) const; uint16 getStopTip(uint32 chain, sint32 surface) const; void setStartTip(uint32 chain, sint32 surface, uint16 startTip); void setStopTip(uint32 chain, sint32 surface, uint16 stopTip); */ uint32 getPreviousChain(uint32 chain, sint32 surface) const; uint32 getNextChain(uint32 chain, sint32 surface) const; public: void dumpSurface(uint surf, const NLMISC::CVector &vect = NLMISC::CVector::Null) const; float distanceToBorder(const ULocalPosition &pos) const; }; }; // NLPACS #endif // NL_LOCAL_RETRIEVER_H /* End of local_retriever.h */