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/>.
19 #include "nel/pacs/chain.h"
22 using namespace NLMISC
;
25 // Functions for vertices comparison.
26 // total order relation
27 static inline bool isStrictlyLess(const CVector
&a
, const CVector
&b
)
29 if (a
.x
< b
.x
) return true;
30 if (a
.x
> b
.x
) return false;
31 if (a
.y
< b
.y
) return true;
32 if (a
.y
> b
.y
) return false;
33 if (a
.z
< b
.y
) return true;
37 static inline bool isStrictlyGreater(const CVector
&a
, const CVector
&b
)
39 if (a
.x
> b
.x
) return true;
40 if (a
.x
< b
.x
) return false;
41 if (a
.y
> b
.y
) return true;
42 if (a
.y
< b
.y
) return false;
43 if (a
.z
> b
.y
) return true;
47 static inline bool isEqual(const CVector
&a
, const CVector
&b
)
53 // COrderedChain3f methods implementation
55 void NLPACS::COrderedChain3f::serial(NLMISC::IStream
&f
)
61 (void)f
.serialVersion(0);
63 f
.serialCont(_Vertices
);
66 f
.serial(_IndexInParent
);
69 // end of COrderedChain3f methods implementation
71 // COrderedChain methods implementation
73 // translates the ordered chain by the vector translation
74 void NLPACS::COrderedChain::translate(const CVector
&translation
)
78 translat
.pack(translation
);
79 for (i
=0; i
<_Vertices
.size(); ++i
)
80 _Vertices
[i
] += translat
;
84 void NLPACS::COrderedChain::traverse(sint from
, sint to
, bool forward
, vector
<NLPACS::CVector2s
> &path
) const
89 if (from
< 0) from
= 0;
90 if (to
< 0) to
= (sint
)_Vertices
.size()-1;
92 for (i
=from
+1; i
<=to
; ++i
)
93 path
.push_back(_Vertices
[i
]);
97 if (from
< 0) from
= (sint
)_Vertices
.size()-2;
100 for (i
=from
; i
>to
; --i
)
101 path
.push_back(_Vertices
[i
]);
106 float NLPACS::COrderedChain::distance(const CVector
&position
) const
108 float minDist
= 1.0e10f
;
110 CVector2f pos
= CVector2f(position
);
112 for (i
=0; i
+1<_Vertices
.size(); ++i
)
114 CVector2f a
= _Vertices
[i
].unpack(),
115 b
= _Vertices
[i
+1].unpack();
118 float len
= d
.norm();
120 CVector2f n
= CVector2f(d
.y
, -d
.x
);
127 dist
= (pos
-a
).norm();
131 dist
= (pos
-b
).norm();
135 dist
= (float)fabs((pos
-a
)*n
);
148 // serializes the ordered chain
149 void NLPACS::COrderedChain::serial(NLMISC::IStream
&f
)
155 - added _Min and _Max vectors
157 sint ver
= f
.serialVersion(1);
159 f
.serialCont(_Vertices
);
162 f
.serial(_IndexInParent
);
167 f
.serial(_Min
, _Max
);
169 else if (f
.isReading() && !_Vertices
.empty())
172 _Max
= _Min
= _Vertices
[0];
173 for (i
=1; i
<_Vertices
.size(); ++i
)
175 _Min
.minof(_Min
, _Vertices
[i
]);
176 _Max
.maxof(_Max
, _Vertices
[i
]);
181 // end of COrderedChain methods implementation
184 // CChain methods implementation
186 // builds the CChain from a list of vertices and a left and right surfaces id.
187 // the chains vector is the vector where to store generated ordered chains.
188 // thisId is the current id of the CChain, and edge is the number of the edge the CChain belongs to (-1
190 void NLPACS::CChain::make(const vector
<CVector
> &vertices
, sint32 left
, sint32 right
, vector
<COrderedChain
> &chains
, uint16 thisId
,
191 vector
<COrderedChain3f
> &fullChains
, vector
<uint
> &useOChainId
)
193 sint first
= 0, last
= 0, i
;
199 // splits the vertices list in ordered sub chains.
200 while (first
< (sint
)vertices
.size()-1)
203 bool forward
= isStrictlyLess(vertices
[first
], vertices
[last
]);
205 // first checks if the subchain goes forward or backward.
207 for (; last
< (sint
)vertices
.size() && isStrictlyLess(vertices
[last
-1], vertices
[last
]); ++last
)
210 for (; last
< (sint
)vertices
.size() && isStrictlyGreater(vertices
[last
-1], vertices
[last
]); ++last
)
214 // inserts the new subchain id within the CChain.
217 if (useOChainId
.empty())
219 subChainId
= (uint32
)chains
.size();
220 if (subChainId
> 65535)
221 nlerror("in NLPACS::CChain::make(): reached the maximum number of ordered chains");
223 chains
.resize(chains
.size()+1);
224 fullChains
.resize(fullChains
.size()+1);
228 subChainId
= useOChainId
.back();
229 useOChainId
.pop_back();
232 _SubChains
.push_back((uint16
)subChainId
);
234 // and creates a new COrderedChain
235 COrderedChain3f
&subchain3f
= fullChains
[subChainId
];
236 subchain3f
._Vertices
.reserve(last
-first
+1);
237 subchain3f
._Forward
= forward
;
238 subchain3f
._ParentId
= thisId
;
239 subchain3f
._IndexInParent
= uint16(_SubChains
.size()-1);
241 // and then copies the vertices (sorted, btw!)
243 for (i
=first
; i
<=last
; ++i
)
244 subchain3f
._Vertices
.push_back(vertices
[i
]);
246 for (i
=last
; i
>=first
; --i
)
247 subchain3f
._Vertices
.push_back(vertices
[i
]);
251 COrderedChain
&subchain
= chains
[subChainId
];
252 subchain
.pack(subchain3f
);
253 subchain
.computeMinMax();
256 for (i
=0; i
<(sint
)subchain
._Vertices
.size()-1; ++i
)
257 length
+= (subchain
._Vertices
[i
+1]-subchain
._Vertices
[i
]).norm();
259 subchain
._Length
= length
;
264 // serializes the CChain
265 void NLPACS::CChain::serial(NLMISC::IStream
&f
)
271 (void)f
.serialVersion(0);
273 f
.serialCont(_SubChains
);
274 f
.serial(_Left
, _Right
);
275 f
.serial(_StartTip
, _StopTip
);
277 f
.serial(_LeftLoop
, _LeftLoopIndex
);
278 f
.serial(_RightLoop
, _RightLoopIndex
);
283 // unifiies the chain
284 void NLPACS::CChain::unify(vector
<NLPACS::COrderedChain
> &ochains
)
289 snap
= (ochains
[_SubChains
[0]].isForward()) ? ochains
[_SubChains
[0]]._Vertices
.back() : ochains
[_SubChains
[0]]._Vertices
.front();
291 for (i
=1; i
<_SubChains
.size(); ++i
)
293 if (ochains
[_SubChains
[i
]].isForward())
295 if (ochains
[_SubChains
[i
]]._Vertices
.front() != snap
)
296 nlwarning("ochain %d and %d are not stuck together", _SubChains
[i
-1], _SubChains
[i
]);
297 ochains
[_SubChains
[i
]]._Vertices
.front() = snap
;
298 snap
= ochains
[_SubChains
[i
]]._Vertices
.back();
302 if (ochains
[_SubChains
[i
]]._Vertices
.back() != snap
)
303 nlwarning("ochain %d and %d are not stuck together", _SubChains
[i
-1], _SubChains
[i
]);
304 ochains
[_SubChains
[i
]]._Vertices
.back() = snap
;
305 snap
= ochains
[_SubChains
[i
]]._Vertices
.front();
312 void NLPACS::CChain::setStartVector(const NLPACS::CVector2s
&v
, vector
<NLPACS::COrderedChain
> &ochains
)
314 if (ochains
[_SubChains
.front()].isForward())
315 ochains
[_SubChains
.front()]._Vertices
.front() = v
;
317 ochains
[_SubChains
.front()]._Vertices
.back() = v
;
321 void NLPACS::CChain::setStopVector(const NLPACS::CVector2s
&v
, vector
<NLPACS::COrderedChain
> &ochains
)
323 if (ochains
[_SubChains
.back()].isForward())
324 ochains
[_SubChains
.back()]._Vertices
.back() = v
;
326 ochains
[_SubChains
.back()]._Vertices
.front() = v
;
330 NLPACS::CVector2s
NLPACS::CChain::getStartVector(vector
<NLPACS::COrderedChain
> &ochains
)
332 if (ochains
[_SubChains
.front()].isForward())
333 return ochains
[_SubChains
.front()]._Vertices
.front();
335 return ochains
[_SubChains
.front()]._Vertices
.back();
339 NLPACS::CVector2s
NLPACS::CChain::getStopVector(vector
<NLPACS::COrderedChain
> &ochains
)
341 if (ochains
[_SubChains
.back()].isForward())
342 return ochains
[_SubChains
.back()]._Vertices
.back();
344 return ochains
[_SubChains
.back()]._Vertices
.front();
347 // end of CChain methods implementation