1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This program is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Affero General Public License as
6 // published by the Free Software Foundation, either version 3 of the
7 // License, or (at your option) any later version.
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Affero General Public License for more details.
14 // You should have received a copy of the GNU Affero General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
17 #ifndef NL_SURFACE_SPLITTER_H
18 #define NL_SURFACE_SPLITTER_H
20 #include "nel/misc/types_nl.h"
22 #include "nel/pacs/local_retriever.h"
23 #include "nel/pacs/quad_grid.h"
28 * TODO Class description
29 * \author Benjamin Legros
30 * \author Nevrax France
33 class CSurfaceSplitter
50 CFixed64() : _Value(0) {}
51 CFixed64(const sint64
&v
) : _Value(v
) {}
52 CFixed64(const double &v
) : _Value((sint64
)(v
*4294967296.0)) {}
53 CFixed64(const CFixed64
&v
) : _Value(v
._Value
) {}
55 operator double(void) const { return ((double)_Value
) / 4294967296.0; }
56 operator float(void) const { return ((float)_Value
) / 4294967296.0f
; }
57 operator sint64(void) const { return _Value
; }
59 CFixed64
operator + (const CFixed64
&f
) const { return CFixed64(_Value
+ f
._Value
); }
60 CFixed64
operator - (const CFixed64
&f
) const { return CFixed64(_Value
- f
._Value
); }
61 CFixed64
operator - () const { return CFixed64(-_Value
); }
62 CFixed64
operator * (const CFixed64
&f
) const
64 sint64 vh
= _Value
>>32;
65 sint64 vl
= _Value
&0xffffffff;
66 sint64 uh
= f
._Value
>>32;
67 sint64 ul
= f
._Value
&0xffffffff;
69 sint64 res
= ((vh
*uh
)<<32)+(vh
*ul
+uh
*vl
)+((uint64
)(vl
*ul
)>>32);
70 double fres
= ((double)res
) / 4294967296.0;
71 double cfres
= (double)(*this) * (double)f
;
74 CFixed64
operator / (const CFixed64
&f
) const
84 a
= -(sint64
)a
, sign
^= 1;
86 b
= -(sint64
)b
, sign
^= 1;
88 uint64 lb
= INT64_CONSTANT (0x8000000000000000);
100 nh
= (nh
+nh
) + (nl
&lb
? 1 : 0);
108 CFixed64
result(sign
? -(sint64
)q
: +(sint64
)q
);
112 CFixed64
&operator += (const CFixed64
&f
) { _Value
+=f
._Value
; return *this; }
113 CFixed64
&operator -= (const CFixed64
&f
) { _Value
-=f
._Value
; return *this; }
114 CFixed64
&operator *= (const CFixed64
&f
) { *this = *this*f
; return *this; }
115 CFixed64
&operator /= (const CFixed64
&f
) { *this = *this/f
; return *this; }
117 bool operator == (const CFixed64
&f
) const { return _Value
== f
._Value
; }
118 bool operator != (const CFixed64
&f
) const { return _Value
!= f
._Value
; }
119 bool operator < (const CFixed64
&f
) const { return _Value
< f
._Value
; }
120 bool operator <= (const CFixed64
&f
) const { return _Value
<= f
._Value
; }
121 bool operator >= (const CFixed64
&f
) const { return _Value
>= f
._Value
; }
122 bool operator > (const CFixed64
&f
) const { return _Value
> f
._Value
; }
124 double sqnorm() const { return (double)(*this * *this); }
125 double norm() const { return sqrt(sqnorm()); }
135 CVector2s64() : x(), y() {}
136 CVector2s64(const sint64
&X
, const sint64
&Y
) : x(X
), y(Y
) {}
137 CVector2s64(const CFixed64
&X
, const CFixed64
&Y
) : x(X
), y(Y
) {}
138 CVector2s64(const NLMISC::CVector
&v
) : x(v
.x
), y(v
.y
) {}
139 CVector2s64(const NLMISC::CVectorD
&v
) : x(v
.x
), y(v
.y
) {}
140 CVector2s64(const NLPACS::CVector2s
&v
) : x(((sint64
)v
.x
) << 25), y(((sint64
)v
.y
) << 25) {}
142 CVector2s64
operator + (const CVector2s64
&v
) const { return CVector2s64(x
+v
.x
, y
+v
.y
); }
143 CVector2s64
operator - (const CVector2s64
&v
) const { return CVector2s64(x
-v
.x
, y
-v
.y
); }
144 CVector2s64
operator * (sint64 s
) const { return CVector2s64(x
*CFixed64(s
), y
*CFixed64(s
)); }
145 CVector2s64
operator * (CFixed64 s
) const { return CVector2s64(x
*s
, y
*s
); }
146 CVector2s64
operator * (double s
) const { return CVector2s64(x
*CFixed64(s
), y
*CFixed64(s
)); }
147 CVector2s64
operator / (sint64 s
) const { return CVector2s64(x
*CFixed64(s
), y
*CFixed64(s
)); }
148 CVector2s64
operator / (CFixed64 s
) const { return CVector2s64(x
*s
, y
*s
); }
149 CVector2s64
operator / (double s
) const { return CVector2s64(x
*CFixed64(s
), y
*CFixed64(s
)); }
150 CFixed64
operator * (const CVector2s64
&v
) const { return x
*v
.x
+ y
*v
.y
; }
151 CFixed64
operator ^ (const CVector2s64
&v
) const { return x
*v
.y
- y
*v
.x
; }
153 bool operator == (const CVector2s64
&v
) const { return x
== v
.x
&& y
== v
.y
; }
154 bool operator != (const CVector2s64
&v
) const { return x
!= v
.x
|| y
!= v
.y
; }
156 CVector2s64
&operator += (const CVector2s64
&v
)
162 CVector2s64
&operator -= (const CVector2s64
&v
)
168 CVector2s64
&operator *= (sint64 s
)
175 CVector2s64
&operator *= (double s
)
183 NLMISC::CVector
asVector() const
185 return NLMISC::CVector((float)x
, (float)y
, 0.0f
);
187 NLMISC::CVectorD
asVectorD() const
189 return NLMISC::CVectorD((double)x
, (double)y
, 0.0);
201 CSurfaceId(uint16 instance
=65535, uint16 surface
=65535, uint16 subsurface
=0) :
204 SubSurface(subsurface
) {}
206 bool operator == (const CSurfaceId
&id
) const { return Instance
== id
.Instance
&& Surface
== id
.Surface
&& SubSurface
== id
.SubSurface
; }
207 bool operator != (const CSurfaceId
&id
) const { return !(*this == id
); }
209 bool operator < (const CSurfaceId
&id
) const
211 if (Instance
< id
.Instance
)
213 else if (Instance
> id
.Instance
)
215 else if (Surface
< id
.Surface
)
217 else if (Surface
> id
.Surface
)
220 return SubSurface
< id
.SubSurface
;
223 bool operator > (const CSurfaceId
&id
) const { return id
< *this; }
224 bool operator <= (const CSurfaceId
&id
) const { return *this == id
|| *this < id
; }
225 bool operator >= (const CSurfaceId
&id
) const { return *this == id
|| id
< *this; }
232 CChainId(uint32 id
=0) : Id(id
) {}
235 bool operator == (const CChainId
&id
) const { return Id
== id
.Id
; }
236 bool operator != (const CChainId
&id
) const { return !(*this == id
); }
237 bool operator < (const CChainId
&id
) const { return Id
< id
.Id
; }
238 bool operator > (const CChainId
&id
) const { return id
< *this; }
239 bool operator <= (const CChainId
&id
) const { return *this == id
|| *this < id
; }
240 bool operator >= (const CChainId
&id
) const { return *this == id
|| id
< *this; }
248 CEdgeId(const CChainId
&chain
=CChainId(), uint edge
=0) : Chain(chain
), Edge(edge
) {}
253 typedef NLPACS::CQuadGrid
<CEdgeId
> TEdgeGrid
;
260 CTipId(uint32 id
=0) : Id(id
) {}
263 bool operator == (const CTipId
&id
) const { return Id
== id
.Id
; }
264 bool operator != (const CTipId
&id
) const { return !(*this == id
); }
265 bool operator < (const CTipId
&id
) const { return Id
< id
.Id
; }
266 bool operator > (const CTipId
&id
) const { return id
< *this; }
267 bool operator <= (const CTipId
&id
) const { return *this == id
|| *this < id
; }
268 bool operator >= (const CTipId
&id
) const { return *this == id
|| id
< *this; }
283 std::vector
<CVector2s64
> Vertices
;
284 std::vector
<TEdgeGrid::CIterator
> Iterators
;
288 CChain() : DontSplit(false) {}
291 void dump(bool forward
) const
293 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
);
297 for (i
=0; i
<(sint
)Vertices
.size(); ++i
, ++j
)
298 NLMISC::InfoLog
->displayRawNL("%d;%.3f;%.3f", j
, (double)Vertices
[i
].x
, (double)Vertices
[i
].y
);
302 for (i
=(sint
)Vertices
.size()-1; i
>=0; --i
, ++j
)
303 NLMISC::InfoLog
->displayRawNL("%d;%.3f;%.3f", j
, (double)Vertices
[i
].x
, (double)Vertices
[i
].y
);
316 std::vector
<CChainId
> Chains
;
326 std::vector
<CChainId
> Chains
;
329 void dump(const CSurfaceSplitter
&splitter
) const
332 for (i
=0; i
<Chains
.size(); ++i
)
334 const CChain
*chain
= splitter
.getChain(Chains
[i
]);
336 chain
->dump(Surface
== chain
->Left
);
341 void removeChain(CChainId chain
)
343 std::vector
<CChainId
>::iterator it
;
344 for (it
=Chains
.begin(); it
!=Chains
.end(); )
347 it
= Chains
.erase(it
);
357 CSurfaceSplitter
*pSplitter
;
363 sint8 ChainDirection
;
365 iterator(CSurfaceSplitter
*splitter
=NULL
, CLoop
*loop
=NULL
, bool forward
=true) : pSplitter(splitter
), pLoop(loop
), Chain(0), pChain(NULL
), ChainVertex(0), Direction(0), ChainDirection(0)
367 Direction
= forward
? +1 : -1;
368 if (splitter
== NULL
|| pLoop
== NULL
)
370 Chain
= (Direction
>0 ? 0 : (sint
)pLoop
->Chains
.size()-1);
373 iterator(const iterator
&it
)
378 iterator
&operator = (const iterator
&it
)
380 pSplitter
= it
.pSplitter
;
384 ChainVertex
= it
.ChainVertex
;
385 Direction
= it
.Direction
;
388 bool operator == (const iterator
&it
)
390 return pSplitter
== it
.pSplitter
&&
393 ChainVertex
== it
.ChainVertex
;
395 bool operator != (const iterator
&it
) { return !(*this == it
); }
398 iterator
&operator ++ ()
400 ChainVertex
+= ChainDirection
;
401 if (ChainVertex
== 0 || ChainVertex
== (sint
)pChain
->Vertices
.size()-1)
411 iterator
operator ++ (int)
415 ChainVertex
+= ChainDirection
;
416 if (ChainVertex
== 0 || ChainVertex
== (sint
)pChain
->Vertices
.size()-1)
427 if (Chain
< 0 || Chain
== (sint
)pLoop
->Chains
.size())
438 pChain
= pSplitter
->getChain(pLoop
->Chains
[Chain
]);
439 ChainDirection
= (pChain
->Left
== pLoop
->Surface
? Direction
: -Direction
);
440 ChainVertex
= (ChainDirection
>0 ? 0 : (sint
)pChain
->Vertices
.size()-1);
443 CVector2s64
operator * () const
445 return pChain
->Vertices
[ChainVertex
];
457 std::vector
<CLoop
> Loops
;
460 void dump(const CSurfaceSplitter
&splitter
) const
462 NLMISC::InfoLog
->displayRawNL("---Surface:%d:%d:%d", Id
.Instance
, Id
.Surface
, Id
.SubSurface
);
464 for (i
=0; i
<Loops
.size(); ++i
)
466 NLMISC::InfoLog
->displayRawNL("Loop:%d", i
);
467 Loops
[i
].dump(splitter
);
472 void removeChain(CChainId chain
)
475 for (i
=0; i
<Loops
.size(); ++i
)
476 Loops
[i
].removeChain(chain
);
481 typedef std::map
<CSurfaceId
, CSurface
> TSurfaceMap
;
482 typedef std::map
<CChainId
, CChain
> TChainMap
;
483 typedef std::map
<CTipId
, CTip
> TTipMap
;
485 TSurfaceMap _Surfaces
;
501 void build(NLPACS::CLocalRetriever
&lr
);
504 CSurface
*getSurface(const CSurfaceId
&id
)
506 TSurfaceMap::iterator it
= _Surfaces
.find(id
);
507 return (it
== _Surfaces
.end() ? NULL
: &((*it
).second
));
511 CChain
*getChain(const CChainId
&id
)
513 TChainMap::iterator it
= _Chains
.find(id
);
514 return (it
== _Chains
.end() ? NULL
: &((*it
).second
));
518 const CSurface
*getSurface(const CSurfaceId
&id
) const
520 TSurfaceMap::const_iterator it
= _Surfaces
.find(id
);
521 return (it
== _Surfaces
.end() ? NULL
: &((*it
).second
));
525 const CChain
*getChain(const CChainId
&id
) const
527 TChainMap::const_iterator it
= _Chains
.find(id
);
528 return (it
== _Chains
.end() ? NULL
: &((*it
).second
));
536 void buildChain(NLPACS::CLocalRetriever
&lr
, uint chain
);
539 void buildSurface(NLPACS::CLocalRetriever
&lr
, uint surface
);
552 void splitChain(TChainMap::iterator it
, uint
&numInters
);
559 TSurfaceMap::const_iterator it
;
561 for (it
=_Surfaces
.begin(); it
!=_Surfaces
.end(); ++it
)
562 (*it
).second
.dump(*this);
566 void dumpChain(CChainId chain
) const
568 TChainMap::const_iterator it
= _Chains
.find(chain
);
569 if (it
== _Chains
.end())
572 (*it
).second
.dump(true);
578 bool intersect(const CVector2s64
&v0
, const CVector2s64
&v1
,
579 const CVector2s64
&c0
, const CVector2s64
&c1
,
580 CVector2s64
&intersect
, CFixed64
&ndist
);
586 CChainId
addChain(const CSurfaceId
&left
, const CSurfaceId
&right
, const std::vector
<CVector2s64
> &points
, bool dontSplit
=false);
589 void removeChain(CChainId chain
);
592 void replaceChain(CChainId chain
, const std::vector
<CChainId
> &chains
);
596 #endif // NL_SURFACE_SPLITTER_H
598 /* End of surface_splitter.h */