khanat-opennel-code/code/nel/tools/pacs/build_rbank/surface_splitter.h

598 lines
14 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_SURFACE_SPLITTER_H
#define NL_SURFACE_SPLITTER_H
#include "nel/misc/types_nl.h"
#include "nel/pacs/local_retriever.h"
#include "nel/pacs/quad_grid.h"
#include <map>
/**
* TODO Class description
* \author Benjamin Legros
* \author Nevrax France
* \date 2002
*/
class CSurfaceSplitter
{
public:
///
class CVector2s64;
class CSurfaceId;
class CChain;
class CLoop;
class CSurface;
///
class CFixed64
{
protected:
sint64 _Value;
public:
CFixed64() : _Value(0) {}
CFixed64(const sint64 &v) : _Value(v) {}
CFixed64(const double &v) : _Value((sint64)(v*4294967296.0)) {}
CFixed64(const CFixed64 &v) : _Value(v._Value) {}
operator double(void) const { return ((double)_Value) / 4294967296.0; }
operator float(void) const { return ((float)_Value) / 4294967296.0f; }
operator sint64(void) const { return _Value; }
CFixed64 operator + (const CFixed64 &f) const { return CFixed64(_Value + f._Value); }
CFixed64 operator - (const CFixed64 &f) const { return CFixed64(_Value - f._Value); }
CFixed64 operator - () const { return CFixed64(-_Value); }
CFixed64 operator * (const CFixed64 &f) const
{
sint64 vh = _Value>>32;
sint64 vl = _Value&0xffffffff;
sint64 uh = f._Value>>32;
sint64 ul = f._Value&0xffffffff;
sint64 res = ((vh*uh)<<32)+(vh*ul+uh*vl)+((uint64)(vl*ul)>>32);
double fres = ((double)res) / 4294967296.0;
double cfres = (double)(*this) * (double)f;
return CFixed64(res);
}
CFixed64 operator / (const CFixed64 &f) const
{
if (f._Value == 0)
return CFixed64();
sint sign = 0;
uint64 a = _Value;
uint64 b = f._Value;
if ((sint64)a < 0)
a = -(sint64)a, sign ^= 1;
if ((sint64)b < 0)
b = -(sint64)b, sign ^= 1;
uint64 lb = INT64_CONSTANT (0x8000000000000000);
uint64 q = 0;
uint64 nh = a>>32;
uint64 nl = a<<32;
while (lb != 0)
{
if (nh >= b)
{
q |= (lb+lb);
nh -= b;
}
nh = (nh+nh) + (nl&lb ? 1 : 0);
lb >>= 1;
}
// round final bit
if (nh >= b)
++q;
CFixed64 result(sign ? -(sint64)q : +(sint64)q );
return result;
}
CFixed64 &operator += (const CFixed64 &f) { _Value+=f._Value; return *this; }
CFixed64 &operator -= (const CFixed64 &f) { _Value-=f._Value; return *this; }
CFixed64 &operator *= (const CFixed64 &f) { *this = *this*f; return *this; }
CFixed64 &operator /= (const CFixed64 &f) { *this = *this/f; return *this; }
bool operator == (const CFixed64 &f) const { return _Value == f._Value; }
bool operator != (const CFixed64 &f) const { return _Value != f._Value; }
bool operator < (const CFixed64 &f) const { return _Value < f._Value; }
bool operator <= (const CFixed64 &f) const { return _Value <= f._Value; }
bool operator >= (const CFixed64 &f) const { return _Value >= f._Value; }
bool operator > (const CFixed64 &f) const { return _Value > f._Value; }
double sqnorm() const { return (double)(*this * *this); }
double norm() const { return sqrt(sqnorm()); }
};
///
class CVector2s64
{
public:
CFixed64 x;
CFixed64 y;
CVector2s64() : x(), y() {}
CVector2s64(const sint64 &X, const sint64 &Y) : x(X), y(Y) {}
CVector2s64(const CFixed64 &X, const CFixed64 &Y) : x(X), y(Y) {}
CVector2s64(const NLMISC::CVector &v) : x(v.x), y(v.y) {}
CVector2s64(const NLMISC::CVectorD &v) : x(v.x), y(v.y) {}
CVector2s64(const NLPACS::CVector2s &v) : x(((sint64)v.x) << 25), y(((sint64)v.y) << 25) {}
CVector2s64 operator + (const CVector2s64 &v) const { return CVector2s64(x+v.x, y+v.y); }
CVector2s64 operator - (const CVector2s64 &v) const { return CVector2s64(x-v.x, y-v.y); }
CVector2s64 operator * (sint64 s) const { return CVector2s64(x*CFixed64(s), y*CFixed64(s)); }
CVector2s64 operator * (CFixed64 s) const { return CVector2s64(x*s, y*s); }
CVector2s64 operator * (double s) const { return CVector2s64(x*CFixed64(s), y*CFixed64(s)); }
CVector2s64 operator / (sint64 s) const { return CVector2s64(x*CFixed64(s), y*CFixed64(s)); }
CVector2s64 operator / (CFixed64 s) const { return CVector2s64(x*s, y*s); }
CVector2s64 operator / (double s) const { return CVector2s64(x*CFixed64(s), y*CFixed64(s)); }
CFixed64 operator * (const CVector2s64 &v) const { return x*v.x + y*v.y; }
CFixed64 operator ^ (const CVector2s64 &v) const { return x*v.y - y*v.x; }
bool operator == (const CVector2s64 &v) const { return x == v.x && y == v.y; }
bool operator != (const CVector2s64 &v) const { return x != v.x || y != v.y; }
CVector2s64 &operator += (const CVector2s64 &v)
{
x += v.x;
y += v.y;
return *this;
}
CVector2s64 &operator -= (const CVector2s64 &v)
{
x -= v.x;
y -= v.y;
return *this;
}
CVector2s64 &operator *= (sint64 s)
{
CFixed64 ss(s);
x *= ss;
y *= ss;
return *this;
}
CVector2s64 &operator *= (double s)
{
CFixed64 ss(s);
x *= ss;
y *= ss;
return *this;
}
NLMISC::CVector asVector() const
{
return NLMISC::CVector((float)x, (float)y, 0.0f);
}
NLMISC::CVectorD asVectorD() const
{
return NLMISC::CVectorD((double)x, (double)y, 0.0);
}
};
///
class CSurfaceId
{
public:
uint16 Instance;
uint16 Surface;
uint16 SubSurface;
CSurfaceId(uint16 instance=65535, uint16 surface=65535, uint16 subsurface=0) :
Instance(instance),
Surface(surface),
SubSurface(subsurface) {}
bool operator == (const CSurfaceId &id) const { return Instance == id.Instance && Surface == id.Surface && SubSurface == id.SubSurface; }
bool operator != (const CSurfaceId &id) const { return !(*this == id); }
bool operator < (const CSurfaceId &id) const
{
if (Instance < id.Instance)
return true;
else if (Instance > id.Instance)
return false;
else if (Surface < id.Surface)
return true;
else if (Surface > id.Surface)
return false;
else
return SubSurface < id.SubSurface;
}
bool operator > (const CSurfaceId &id) const { return id < *this; }
bool operator <= (const CSurfaceId &id) const { return *this == id || *this < id; }
bool operator >= (const CSurfaceId &id) const { return *this == id || id < *this; }
};
///
class CChainId
{
public:
CChainId(uint32 id=0) : Id(id) {}
uint32 Id;
bool operator == (const CChainId &id) const { return Id == id.Id; }
bool operator != (const CChainId &id) const { return !(*this == id); }
bool operator < (const CChainId &id) const { return Id < id.Id; }
bool operator > (const CChainId &id) const { return id < *this; }
bool operator <= (const CChainId &id) const { return *this == id || *this < id; }
bool operator >= (const CChainId &id) const { return *this == id || id < *this; }
};
///
class CEdgeId
{
public:
CEdgeId(const CChainId &chain=CChainId(), uint edge=0) : Chain(chain), Edge(edge) {}
CChainId Chain;
uint Edge;
};
typedef NLPACS::CQuadGrid<CEdgeId> TEdgeGrid;
///
class CTipId
{
public:
CTipId(uint32 id=0) : Id(id) {}
uint32 Id;
bool operator == (const CTipId &id) const { return Id == id.Id; }
bool operator != (const CTipId &id) const { return !(*this == id); }
bool operator < (const CTipId &id) const { return Id < id.Id; }
bool operator > (const CTipId &id) const { return id < *this; }
bool operator <= (const CTipId &id) const { return *this == id || *this < id; }
bool operator >= (const CTipId &id) const { return *this == id || id < *this; }
};
///
class CChain
{
public:
CChainId Id;
CSurfaceId Left;
CSurfaceId Right;
CTipId Start;
CTipId Stop;
std::vector<CVector2s64> Vertices;
std::vector<TEdgeGrid::CIterator> Iterators;
bool DontSplit;
///
CChain() : DontSplit(false) {}
///
void dump(bool forward) const
{
NLMISC::InfoLog->displayRawNL("Chain:%d[Left=%d:%d:%d,Right=%d:%d:%d]", Id.Id, Left.Instance, Left.Surface, Left.SubSurface, Right.Instance, Right.Surface, Right.SubSurface);
sint i, j=0;
if (forward)
{
for (i=0; i<(sint)Vertices.size(); ++i, ++j)
NLMISC::InfoLog->displayRawNL("%d;%.3f;%.3f", j, (double)Vertices[i].x, (double)Vertices[i].y);
}
else
{
for (i=(sint)Vertices.size()-1; i>=0; --i, ++j)
NLMISC::InfoLog->displayRawNL("%d;%.3f;%.3f", j, (double)Vertices[i].x, (double)Vertices[i].y);
}
}
};
///
class CTip
{
public:
CTipId Id;
CVector2s64 Tip;
std::vector<CChainId> Chains;
};
///
class CLoop
{
public:
CSurfaceId Surface;
std::vector<CChainId> Chains;
///
void dump(const CSurfaceSplitter &splitter) const
{
uint i;
for (i=0; i<Chains.size(); ++i)
{
const CChain *chain = splitter.getChain(Chains[i]);
if (chain != NULL)
chain->dump(Surface == chain->Left);
}
}
///
void removeChain(CChainId chain)
{
std::vector<CChainId>::iterator it;
for (it=Chains.begin(); it!=Chains.end(); )
{
if (*it == chain)
it = Chains.erase(it);
else
++it;
}
}
///
class iterator
{
public:
CSurfaceSplitter *pSplitter;
CLoop *pLoop;
sint Chain;
CChain *pChain;
sint ChainVertex;
sint8 Direction;
sint8 ChainDirection;
iterator(CSurfaceSplitter *splitter=NULL, CLoop *loop=NULL, bool forward=true) : pSplitter(splitter), pLoop(loop), Chain(0), pChain(NULL), ChainVertex(0), Direction(0), ChainDirection(0)
{
Direction = forward ? +1 : -1;
if (splitter == NULL || pLoop == NULL)
return;
Chain = (Direction>0 ? 0 : (sint)pLoop->Chains.size()-1);
resetChain();
}
iterator(const iterator &it)
{
*this = it;
}
iterator &operator = (const iterator &it)
{
pSplitter = it.pSplitter;
pLoop = it.pLoop;
Chain = it.Chain;
pChain = it.pChain;
ChainVertex = it.ChainVertex;
Direction = it.Direction;
return *this;
}
bool operator == (const iterator &it)
{
return pSplitter == it.pSplitter &&
pLoop == it.pLoop &&
Chain == it.Chain &&
ChainVertex == it.ChainVertex;
}
bool operator != (const iterator &it) { return !(*this == it); }
// ++it
iterator &operator ++ ()
{
ChainVertex += ChainDirection;
if (ChainVertex == 0 || ChainVertex == (sint)pChain->Vertices.size()-1)
{
Chain += Direction;
resetChain();
}
return *this;
}
// it++
iterator operator ++ (int)
{
iterator tmp(*this);
ChainVertex += ChainDirection;
if (ChainVertex == 0 || ChainVertex == (sint)pChain->Vertices.size()-1)
{
Chain += Direction;
resetChain();
}
return tmp;
}
void resetChain()
{
if (Chain < 0 || Chain == (sint)pLoop->Chains.size())
{
pSplitter = NULL;
pLoop = NULL;
Chain = 0;
pChain = NULL;
ChainVertex = 0;
Direction = 0;
ChainDirection = 0;
return;
}
pChain = pSplitter->getChain(pLoop->Chains[Chain]);
ChainDirection = (pChain->Left == pLoop->Surface ? Direction : -Direction);
ChainVertex = (ChainDirection>0 ? 0 : (sint)pChain->Vertices.size()-1);
}
CVector2s64 operator * () const
{
return pChain->Vertices[ChainVertex];
}
};
};
///
class CSurface
{
public:
CSurfaceId Id;
std::vector<CLoop> Loops;
///
void dump(const CSurfaceSplitter &splitter) const
{
NLMISC::InfoLog->displayRawNL("---Surface:%d:%d:%d", Id.Instance, Id.Surface, Id.SubSurface);
uint i;
for (i=0; i<Loops.size(); ++i)
{
NLMISC::InfoLog->displayRawNL("Loop:%d", i);
Loops[i].dump(splitter);
}
}
///
void removeChain(CChainId chain)
{
uint i;
for (i=0; i<Loops.size(); ++i)
Loops[i].removeChain(chain);
}
};
protected:
typedef std::map<CSurfaceId, CSurface> TSurfaceMap;
typedef std::map<CChainId, CChain> TChainMap;
typedef std::map<CTipId, CTip> TTipMap;
TSurfaceMap _Surfaces;
uint _NumSurfaces;
TChainMap _Chains;
uint _NumChains;
TTipMap _Tips;
uint _NumTips;
TEdgeGrid _Edges;
public:
/// Constructor
CSurfaceSplitter();
///
void build(NLPACS::CLocalRetriever &lr);
///
CSurface *getSurface(const CSurfaceId &id)
{
TSurfaceMap::iterator it = _Surfaces.find(id);
return (it == _Surfaces.end() ? NULL : &((*it).second));
}
///
CChain *getChain(const CChainId &id)
{
TChainMap::iterator it = _Chains.find(id);
return (it == _Chains.end() ? NULL : &((*it).second));
}
///
const CSurface *getSurface(const CSurfaceId &id) const
{
TSurfaceMap::const_iterator it = _Surfaces.find(id);
return (it == _Surfaces.end() ? NULL : &((*it).second));
}
///
const CChain *getChain(const CChainId &id) const
{
TChainMap::const_iterator it = _Chains.find(id);
return (it == _Chains.end() ? NULL : &((*it).second));
}
protected:
///
void buildChain(NLPACS::CLocalRetriever &lr, uint chain);
///
void buildSurface(NLPACS::CLocalRetriever &lr, uint surface);
///
void initEdgeGrid();
///
void splitChains();
///
void splitChain(TChainMap::iterator it, uint &numInters);
///
void dump() const
{
TSurfaceMap::const_iterator it;
for (it=_Surfaces.begin(); it!=_Surfaces.end(); ++it)
(*it).second.dump(*this);
}
///
void dumpChain(CChainId chain) const
{
TChainMap::const_iterator it = _Chains.find(chain);
if (it == _Chains.end())
return;
(*it).second.dump(true);
}
///
bool intersect(const CVector2s64 &v0, const CVector2s64 &v1,
const CVector2s64 &c0, const CVector2s64 &c1,
CVector2s64 &intersect, CFixed64 &ndist);
///
CChainId addChain(const CSurfaceId &left, const CSurfaceId &right, const std::vector<CVector2s64> &points, bool dontSplit=false);
///
void removeChain(CChainId chain);
///
void replaceChain(CChainId chain, const std::vector<CChainId> &chains);
};
#endif // NL_SURFACE_SPLITTER_H
/* End of surface_splitter.h */