Merge branch 'fixes' into main/rendor-staging
[ryzomcore.git] / nel / src / pacs / chain.cpp
blobf908cc8754fc66fdaa109e9aa37aee073319a229
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
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.
8 //
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 #include "stdpacs.h"
19 #include "nel/pacs/chain.h"
21 using namespace std;
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;
34 return false;
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;
44 return false;
47 static inline bool isEqual(const CVector &a, const CVector &b)
49 return (a == b);
53 // COrderedChain3f methods implementation
55 void NLPACS::COrderedChain3f::serial(NLMISC::IStream &f)
58 Version 0:
59 - base version.
61 (void)f.serialVersion(0);
63 f.serialCont(_Vertices);
64 f.serial(_Forward);
65 f.serial(_ParentId);
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)
76 uint i;
77 CVector2s translat;
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
86 sint i;
87 if (forward)
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]);
95 else
97 if (from < 0) from = (sint)_Vertices.size()-2;
98 if (to < 0) to = -1;
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;
109 uint i;
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();
117 CVector2f d = (b-a);
118 float len = d.norm();
119 d /= len;
120 CVector2f n = CVector2f(d.y, -d.x);
122 float l = (pos-a)*d;
123 float dist;
125 if (l < 0.0f)
127 dist = (pos-a).norm();
129 else if (l > len)
131 dist = (pos-b).norm();
133 else
135 dist = (float)fabs((pos-a)*n);
138 if (dist < minDist)
140 minDist = dist;
144 return minDist;
148 // serializes the ordered chain
149 void NLPACS::COrderedChain::serial(NLMISC::IStream &f)
152 Version 0:
153 - base version.
154 Version 1:
155 - added _Min and _Max vectors
157 sint ver= f.serialVersion(1);
159 f.serialCont(_Vertices);
160 f.serial(_Forward);
161 f.serial(_ParentId);
162 f.serial(_IndexInParent);
163 f.serial(_Length);
165 if (ver >= 1)
167 f.serial(_Min, _Max);
169 else if (f.isReading() && !_Vertices.empty())
171 uint i;
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
189 // if none.)
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;
195 _Left = left;
196 _Right = right;
197 _Length = 0.0f;
199 // splits the vertices list in ordered sub chains.
200 while (first < (sint)vertices.size()-1)
202 last = first+1;
203 bool forward = isStrictlyLess(vertices[first], vertices[last]);
205 // first checks if the subchain goes forward or backward.
206 if (forward)
207 for (; last < (sint)vertices.size() && isStrictlyLess(vertices[last-1], vertices[last]); ++last)
209 else
210 for (; last < (sint)vertices.size() && isStrictlyGreater(vertices[last-1], vertices[last]); ++last)
212 --last;
214 // inserts the new subchain id within the CChain.
215 uint32 subChainId;
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);
226 else
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!)
242 if (forward)
243 for (i=first; i<=last; ++i)
244 subchain3f._Vertices.push_back(vertices[i]);
245 else
246 for (i=last; i>=first; --i)
247 subchain3f._Vertices.push_back(vertices[i]);
249 first = last;
251 COrderedChain &subchain = chains[subChainId];
252 subchain.pack(subchain3f);
253 subchain.computeMinMax();
255 float length = 0.0f;
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;
260 _Length += length;
264 // serializes the CChain
265 void NLPACS::CChain::serial(NLMISC::IStream &f)
268 Version 0:
269 - base version.
271 (void)f.serialVersion(0);
273 f.serialCont(_SubChains);
274 f.serial(_Left, _Right);
275 f.serial(_StartTip, _StopTip);
276 f.serial(_Length);
277 f.serial(_LeftLoop, _LeftLoopIndex);
278 f.serial(_RightLoop, _RightLoopIndex);
283 // unifiies the chain
284 void NLPACS::CChain::unify(vector<NLPACS::COrderedChain> &ochains)
286 CVector2s snap;
287 uint i;
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();
300 else
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;
316 else
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;
325 else
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();
334 else
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();
343 else
344 return ochains[_SubChains.back()]._Vertices.front();
347 // end of CChain methods implementation