649 lines
19 KiB
C++
649 lines
19 KiB
C++
// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
|
|
// 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 <http://www.gnu.org/licenses/>.
|
|
|
|
#ifndef NL_LOCAL_RETRIEVER_H
|
|
#define NL_LOCAL_RETRIEVER_H
|
|
|
|
#include <vector>
|
|
#include <string>
|
|
#include <list>
|
|
|
|
#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<CChainTip> 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<sint32>
|
|
{
|
|
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;
|
|
_IndexInOChain = 0;
|
|
_MaxIndexInOChain = 0;
|
|
_OChainForward = 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<COrderedChain> _OrderedChains;
|
|
std::vector<COrderedChain3f> _FullOrderedChains;
|
|
|
|
/// The chains insinde the zone.
|
|
std::vector<CChain> _Chains;
|
|
|
|
/// The surfaces inside the zone.
|
|
std::vector<CRetrievableSurface> _Surfaces;
|
|
|
|
/// The bbox of the local retriever
|
|
NLMISC::CAABBox _BBox;
|
|
|
|
/// The tips making links between different chains.
|
|
std::vector<CTip> __Tips;
|
|
|
|
/// The chains on the edges of the zone.
|
|
std::vector<uint16> _BorderChains;
|
|
|
|
/// The topologies within the zone.
|
|
std::vector<CTopology> _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<NLMISC::CVector> _InteriorVertices;
|
|
|
|
/// The faces of the collision mesh
|
|
std::vector<CInteriorFace> _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<CTip> &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<COrderedChain> &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<COrderedChain3f> &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<CChain> &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<uint16> &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<CRetrievableSurface> &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<NLMISC::CVector> &getInteriorVertices() const { return _InteriorVertices; }
|
|
|
|
/// Returns the interior faces
|
|
const std::vector<CInteriorFace> &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<NLMISC::CAABBox> &surfaceBBoxes) const;
|
|
|
|
/// Builds the polygons (loops) of a given surface
|
|
void buildSurfacePolygons(uint32 surface, std::list<NLMISC::CPolygon> &polygons) const;
|
|
|
|
/// Builds the polygons (loops) of all surfaces in the retriever
|
|
void buildSurfacePolygons(std::list< std::list<NLMISC::CPolygon> > &polygons) const
|
|
{
|
|
uint i;
|
|
for (i=0; i<_Surfaces.size(); ++i)
|
|
{
|
|
polygons.push_back(std::list<NLMISC::CPolygon>());
|
|
buildSurfacePolygons(i, polygons.back());
|
|
}
|
|
}
|
|
|
|
/// Builds the polygons (loops) of a given surface
|
|
void build3dSurfacePolygons(uint32 surface, std::list<NLMISC::CPolygon> &polygons) const;
|
|
|
|
/// Builds the polygons (loops) of all surfaces in the retriever
|
|
void build3dSurfacePolygons(std::list< std::list<NLMISC::CPolygon> > &polygons) const
|
|
{
|
|
uint i;
|
|
for (i=0; i<_Surfaces.size(); ++i)
|
|
{
|
|
polygons.push_back(std::list<NLMISC::CPolygon>());
|
|
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<NLMISC::CVector> &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<NLMISC::CVector> &getInteriorVertices() { return _InteriorVertices; }
|
|
|
|
/// Returns the interior faces
|
|
std::vector<CInteriorFace> &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<COrderedChain3f> &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<CVector2s> &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<NLMISC::CVector> Vertices;
|
|
};
|
|
|
|
// temp object to store replaced ochain ids
|
|
std::vector<uint> FreeOChains;
|
|
|
|
void replaceChain(uint32 chainId, const std::vector<CChainReplacement> &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 */
|