1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2015-2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
24 #include "nel/misc/plane.h"
26 #include "nel/pacs/local_retriever.h"
27 #include "nel/pacs/collision_desc.h"
28 #include "nel/pacs/retriever_instance.h"
30 #include "nel/misc/hierarchical_timer.h"
34 using namespace NLMISC
;
36 /// The max distance allowed to merge tips.
37 const float NLPACS::CLocalRetriever::_TipThreshold
= 0.1f
;
38 const float NLPACS::CLocalRetriever::_EdgeTipThreshold
= 0.1f
;
40 /// The threshold distance to insure a position belongs to a surface
41 const float InsurePositionThreshold
= 2.0e-2f
;
43 //static float hybrid2dNorm(const CVector &v)
45 // return (float)(sqrt(sqr(v.x)+sqr(v.y))+fabs(v.z)*0.1);
52 NLPACS::CLocalRetriever::CLocalRetriever()
56 LoadCheckFlag
= false;
60 void NLPACS::CLocalRetriever::clear()
62 contReset(_OrderedChains
);
63 contReset(_FullOrderedChains
);
67 contReset(_BorderChains
);
69 for (i
=0; i
<NumMaxCreatureModels
; ++i
)
70 contReset(_Topologies
[i
]);
72 _ExteriorMesh
.clear();
73 contReset(_InteriorVertices
);
74 contReset(_InteriorFaces
);
78 LoadCheckFlag
= false;
82 const CVector
&NLPACS::CLocalRetriever::getStartVector(uint32 chain
) const
84 const COrderedChain3f
&ochain
= _FullOrderedChains
[_Chains
[chain
].getSubChains().front()];
85 return (ochain
.isForward()) ? ochain
.getVertices().front() : ochain
.getVertices().back();
88 const CVector
&NLPACS::CLocalRetriever::getStopVector(uint32 chain
) const
90 const COrderedChain3f
&ochain
= _FullOrderedChains
[_Chains
[chain
].getSubChains().back()];
91 return (ochain
.isForward()) ? ochain
.getVertices().back() : ochain
.getVertices().front();
97 const CVector
&NLPACS::CLocalRetriever::getStartVector(uint32 chain
, sint32 surface
) const
99 bool onLeft
= _Chains
[chain
].getLeft() == surface
;
100 const COrderedChain3f
&ochain
= onLeft
? _FullOrderedChains
[_Chains
[chain
].getSubChains().front()] :
101 _FullOrderedChains
[_Chains
[chain
].getSubChains().back()];
103 if (ochain
.isForward() == onLeft
)
104 return ochain
.getVertices().front();
106 return ochain
.getVertices().back();
109 const CVector
&NLPACS::CLocalRetriever::getStopVector(uint32 chain
, sint32 surface
) const
111 bool onLeft
= _Chains
[chain
].getLeft() == surface
;
112 const COrderedChain3f
&ochain
= onLeft
? _FullOrderedChains
[_Chains
[chain
].getSubChains().back()] :
113 _FullOrderedChains
[_Chains
[chain
].getSubChains().front()];
115 if (ochain
.isForward() == onLeft
)
116 return ochain
.getVertices().back();
118 return ochain
.getVertices().front();
124 uint16 NLPACS::CLocalRetriever::getStartTip(uint32 chain, sint32 surface) const
126 return (_Chains[chain].getLeft() == surface) ? _Chains[chain].getStartTip() : _Chains[chain].getStopTip();
129 uint16 NLPACS::CLocalRetriever::getStopTip(uint32 chain, sint32 surface) const
131 return (_Chains[chain].getLeft() == surface) ? _Chains[chain].getStopTip() : _Chains[chain].getStartTip();
138 void NLPACS::CLocalRetriever::setStartTip(uint32 chain, sint32 surface, uint16 startTip)
140 if (_Chains[chain].getLeft() == surface)
141 _Chains[chain]._StartTip = startTip;
143 _Chains[chain]._StopTip = startTip;
146 void NLPACS::CLocalRetriever::setStopTip(uint32 chain, sint32 surface, uint16 stopTip)
148 if (_Chains[chain].getLeft() == surface)
149 _Chains[chain]._StopTip = stopTip;
151 _Chains[chain]._StartTip = stopTip;
157 uint32
NLPACS::CLocalRetriever::getPreviousChain(uint32 chain
, sint32 surface
) const
162 if (_Chains
[chain
].getLeft() == surface
)
164 loop
= _Chains
[chain
]._LeftLoop
;
165 loopIndex
= _Chains
[chain
]._LeftLoopIndex
;
169 loop
= _Chains
[chain
]._RightLoop
;
170 loopIndex
= _Chains
[chain
]._RightLoopIndex
;
173 const CRetrievableSurface
&surf
= _Surfaces
[surface
];
174 const CRetrievableSurface::TLoop
&sLoop
= surf
._Loops
[loop
];
175 return surf
._Chains
[sLoop
[(loopIndex
+sLoop
.size()-1)%sLoop
.size()]].Chain
;
178 uint32
NLPACS::CLocalRetriever::getNextChain(uint32 chain
, sint32 surface
) const
183 if (_Chains
[chain
].getLeft() == surface
)
185 loop
= _Chains
[chain
]._LeftLoop
;
186 loopIndex
= _Chains
[chain
]._LeftLoopIndex
;
190 loop
= _Chains
[chain
]._RightLoop
;
191 loopIndex
= _Chains
[chain
]._RightLoopIndex
;
194 const CRetrievableSurface
&surf
= _Surfaces
[surface
];
195 const CRetrievableSurface::TLoop
&sLoop
= surf
._Loops
[loop
];
196 return surf
._Chains
[sLoop
[(loopIndex
+1)%sLoop
.size()]].Chain
;
202 void NLPACS::CLocalRetriever::unify()
207 for (i=0; i<_Chains.size(); ++i)
208 _Chains[i].unify(_OrderedChains);
210 for (i=0; i<_Tips.size(); ++i)
212 NLPACS::CLocalRetriever::CTip &tip = _Tips[i];
213 CVector2s ptip = tip.Point;
215 for (j=0; j<tip.Chains.size(); ++j)
217 if (tip.Chains[j].Start)
219 if (_Chains[tip.Chains[j].Chain].getStartVector(_OrderedChains) != ptip)
220 nlwarning("chain %d is not stuck to tip %d", tip.Chains[j].Chain, i);
221 _Chains[tip.Chains[j].Chain].setStartVector(ptip, _OrderedChains);
225 if (_Chains[tip.Chains[j].Chain].getStopVector(_OrderedChains) != ptip)
226 nlwarning("chain %d is not stuck to tip %d", tip.Chains[j].Chain, i);
227 _Chains[tip.Chains[j].Chain].setStopVector(ptip, _OrderedChains);
232 _FullOrderedChains.resize(_OrderedChains.size());
233 for (i=0; i<_OrderedChains.size(); ++i)
234 _FullOrderedChains[i].unpack(_OrderedChains[i]);
244 void NLPACS::CLocalRetriever::dumpSurface(uint surf
, const CVector
&vect
) const
246 const CRetrievableSurface
&surface
= _Surfaces
[surf
];
248 nlinfo("dump surf %d", surf
);
249 nlinfo("%d chains, %d loops", surface
._Chains
.size(), surface
._Loops
.size());
253 for (i
=0; i
<surface
._Chains
.size(); ++i
)
255 uint chainId
= surface
._Chains
[i
].Chain
;
256 const CChain
&chain
= _Chains
[chainId
];
257 nlinfo("-- chain %d[%d]: %d sub left=%d right=%d start=%d stop=%d", i
, chainId
, chain
.getSubChains().size(), chain
.getLeft(), chain
.getRight(), chain
.getStartTip(), chain
.getStopTip());
259 for (j
=0; j
<chain
.getSubChains().size(); ++j
)
261 const COrderedChain3f
&ochain
= _FullOrderedChains
[chain
.getSubChain(j
)];
262 const COrderedChain
&ochains
= _OrderedChains
[chain
.getSubChain(j
)];
263 nlinfo(" subchain %d[%d]: fwd=%d parent=%d idx=%d", j
, chain
.getSubChain(j
), ochain
.isForward(), ochain
.getParentId(), ochain
.getIndexInParent());
264 for (k
=0; k
<ochain
.getVertices().size(); ++k
)
265 nlinfo(" v[%d]=(%.3f,%.3f,%.3f) (%d,%d)", k
, ochain
.getVertices()[k
].x
+vect
.x
, ochain
.getVertices()[k
].y
+vect
.y
, ochain
.getVertices()[k
].z
+vect
.z
, ochains
.getVertices()[k
].x
, ochains
.getVertices()[k
].y
);
270 for (i
=0; i
<surface
._Loops
.size(); ++i
)
272 const CRetrievableSurface::TLoop
&loop
= surface
._Loops
[i
];
273 nlinfo("-- loop %d: %d chains length=%.2f", i
, loop
.size(), loop
.Length
);
276 sprintf(wbuffer
, " chains:");
278 for (j
=0; j
<loop
.size(); ++j
)
280 sprintf(wbuffer
, " %d[%d]", loop
[j
], surface
._Chains
[loop
[j
]].Chain
);
283 nlinfo("%s", ss
.str().c_str());
288 float NLPACS::CLocalRetriever::distanceToBorder(const ULocalPosition
&pos
) const
293 const CRetrievableSurface
&surf
= _Surfaces
[pos
.Surface
];
295 float minDist
= 1.0e10f
, dist
;
297 for (i
=0; i
<surf
._Chains
.size(); ++i
)
299 const CChain
&chain
= _Chains
[surf
._Chains
[i
].Chain
];
300 for (j
=0; j
<chain
.getSubChains().size(); ++j
)
302 dist
= _OrderedChains
[chain
.getSubChain(j
)].distance(pos
.Estimation
);
317 sint32
NLPACS::CLocalRetriever::addSurface(uint8 normalq
, uint8 orientationq
,
318 uint8 mat
, uint8 charact
, uint8 level
,
319 bool isUnderWater
, float waterHeight
,
321 const CVector
¢er
,
322 const NLPACS::CSurfaceQuadTree
&quad
,
325 // creates a new surface...
326 sint32 newId
= (sint32
)_Surfaces
.size();
327 _Surfaces
.resize(newId
+1);
328 CRetrievableSurface
&surf
= _Surfaces
.back();
331 surf
._NormalQuanta
= normalq
;
332 surf
._OrientationQuanta
= orientationq
;
333 surf
._Material
= mat
;
334 surf
._Character
= charact
;
337 surf
._Center
= center
;
338 surf
._QuantHeight
= quantHeight
;
340 // WARNING!! MODIFY THESE IF QUANTAS VALUES CHANGE !!
341 surf
._IsFloor
= (surf
._NormalQuanta
<= 1);
342 surf
._IsCeiling
= (surf
._NormalQuanta
>= 3);
345 surf
._Flags
|= (surf
._IsFloor
) ? (1<<CRetrievableSurface::IsFloorBit
) : 0;
346 surf
._Flags
|= (surf
._IsCeiling
) ? (1<<CRetrievableSurface::IsCeilingBit
) : 0;
347 surf
._Flags
|= (!surf
._IsFloor
&& !surf
._IsCeiling
) ? (1<<CRetrievableSurface::IsSlantBit
) : 0;
348 surf
._Flags
|= clusterHint
? (1<<CRetrievableSurface::ClusterHintBit
) : 0;
350 surf
._Flags
|= (isUnderWater
) ? (1<<CRetrievableSurface::IsUnderWaterBit
) : 0;
351 surf
._WaterHeight
= waterHeight
;
353 surf
._Flags
|= ((0xffffffff<<(CRetrievableSurface::NormalQuantasStartBit
)) & CRetrievableSurface::NormalQuantasBitMask
);
358 sint32
NLPACS::CLocalRetriever::addChain(const vector
<CVector
> &verts
,
359 sint32 left
, sint32 right
)
361 vector
<CVector
> vertices
= verts
;
364 if (vertices
.size() < 2)
366 nlwarning("in NLPACS::CLocalRetriever::addChain()");
367 nlwarning("The chain has less than 2 vertices");
371 // Remove doubled vertices due to CVector2s snapping
372 vector
<CVector2s
> converts
;
374 for (i
=0; i
<vertices
.size(); ++i
)
375 converts
.push_back(CVector2s(vertices
[i
]));
377 vector
<CVector2s
>::iterator next2s
= converts
.begin(), it2s
, prev2s
;
378 prev2s
= next2s
; ++next2s
;
379 it2s
= next2s
; ++next2s
;
381 vector
<CVector
>::iterator it3f
= vertices
.begin();
382 CVector prev3f
= *it3f
;
386 for (; it2s
!= converts
.end() && next2s
!= converts
.end(); )
388 // if the next point is equal to the previous
389 if (*it2s
== *prev2s
|| *it2s
== *next2s
)
391 // then remove the next point
392 it2s
= converts
.erase(it2s
);
393 it3f
= vertices
.erase(it3f
);
402 // else remember the next point, and step to the next...
411 if (vertices
.size() < 2)
413 nlwarning("in NLPACS::CLocalRetriever::addChain()");
414 nlwarning("The chain was snapped to a single point");
418 sint32 newId
= (sint32
)_Chains
.size();
419 _Chains
.resize(newId
+1);
420 CChain
&chain
= _Chains
.back();
422 if (left
>(sint
)_Surfaces
.size())
423 nlerror ("left surface id MUST be id<%d (id=%d)", _Surfaces
.size(), left
);
424 if (right
>(sint
)_Surfaces
.size())
425 nlerror ("right surface id MUST be id<%d (id=%d)", _Surfaces
.size(), right
);
427 // checks if we can build the chain.
429 nlerror("in NLPACS::CLocalRetriever::addChain(): reached the maximum number of chains");
431 CRetrievableSurface
*leftSurface
= (left
>=0) ? &(_Surfaces
[left
]) : NULL
;
432 CRetrievableSurface
*rightSurface
= (right
>=0) ? &(_Surfaces
[right
]) : NULL
;
434 // adds the chain and the link to the surface links vector.
435 if (leftSurface
!= NULL
)
436 leftSurface
->_Chains
.push_back(CRetrievableSurface::CSurfaceLink(newId
, right
));
437 if (rightSurface
!= NULL
)
438 rightSurface
->_Chains
.push_back(CRetrievableSurface::CSurfaceLink(newId
, left
));
440 chain
._StartTip
= 0xffff;
441 chain
._StopTip
= 0xffff;
443 // make the chain and its subchains.
445 chain
.make(vertices
, left
, right
, _OrderedChains
, (uint16
)newId
, _FullOrderedChains
, empty
);
453 void NLPACS::CLocalRetriever::computeLoopsAndTips()
456 // examine each chain tip to match another tip inside the surface tips
457 // if there is no matching tip, then creates a new one
461 for (i
=0; i
<_Surfaces
.size(); ++i
)
463 CRetrievableSurface
&surface
= _Surfaces
[i
];
465 vector
<bool> chainFlags
;
466 chainFlags
.resize(surface
._Chains
.size());
467 for (j
=0; j
<chainFlags
.size(); ++j
)
468 chainFlags
[j
] = false;
474 for (j
=0; j
<chainFlags
.size() && chainFlags
[j
]; ++j
)
477 if (j
== chainFlags
.size())
480 uint32 loopId
= (uint32
)surface
._Loops
.size();
481 surface
._Loops
.push_back(CRetrievableSurface::TLoop());
482 CRetrievableSurface::TLoop
&loop
= surface
._Loops
.back();
484 CVector loopStart
= getStartVector(surface
._Chains
[j
].Chain
, i
);
485 CVector currentEnd
= getStopVector(surface
._Chains
[j
].Chain
, i
);
486 _Chains
[surface
._Chains
[j
].Chain
].setLoopIndexes(i
, loopId
, (uint
)loop
.size());
487 loop
.push_back(uint16(j
));
488 chainFlags
[j
] = true;
490 float loopCloseDistance
;
494 // loopCloseDistance = hybrid2dNorm(loopStart-currentEnd);
495 loopCloseDistance
= (loopStart
-currentEnd
).norm();
497 // choose the best matching start vector
499 float best
= 1.0e10f
;
501 for (j
=0; j
<chainFlags
.size(); ++j
)
505 thisStart
= getStartVector(surface
._Chains
[j
].Chain
, i
);
506 // float d = hybrid2dNorm(thisStart-currentEnd);
507 float d
= (thisStart
-currentEnd
).norm();
515 if ((bestChain
== -1 || best
> 4.0e-2f
)&& loopCloseDistance
> 4.0e-2f
)
517 nlwarning("in NLPACS::CLocalRetriever::computeTips()");
521 for (j
=0; j
<surface
._Chains
.size(); ++j
)
523 CVector start
= getStartVector(surface
._Chains
[j
].Chain
, i
);
524 CVector end
= getStopVector(surface
._Chains
[j
].Chain
, i
);
525 nlinfo("surf=%d chain=%d", i
, surface
._Chains
[j
].Chain
);
526 nlinfo("start=(%f,%f,%f)", start
.x
, start
.y
, start
.z
);
527 nlinfo("end=(%f,%f,%f)", end
.x
, end
.y
, end
.z
);
530 nlwarning("bestChain=%d best=%f", bestChain
, best
);
531 nlwarning("loopCloseDistance=%f", loopCloseDistance
);
532 nlerror("Couldn't close loop on surface=%d", i
);
534 else if ((best
> 1.0e0f
&& loopCloseDistance
< 3.0e-2f
) ||
535 loopCloseDistance
< 1.0e-3f
)
540 currentEnd
= getStopVector(surface
._Chains
[bestChain
].Chain
, i
);
541 _Chains
[surface
._Chains
[bestChain
].Chain
].setLoopIndexes(i
, loopId
, (uint
)loop
.size());
542 loop
.push_back(uint16(bestChain
));
543 chainFlags
[bestChain
] = true;
552 for (i=0; i<_Chains.size(); ++i)
558 // for both tips (start and stop)
559 for (whichTip=0; whichTip<=1; ++whichTip)
562 uint thisTip = (whichTip) ? _Chains[i].getStopTip() : _Chains[i].getStartTip();
564 if (thisTip != 0xffff && thisTip >= _Tips.size())
566 nlwarning("in NLPACS::CLocalRetriever::computeLoopsAndTips()");
567 nlerror("checked a tip that doesn't exist on chain %d (tipId=%d)", i, thisTip);
570 // if it is unaffected yet creates an new tip and affect it to the common chains
571 if (thisTip == 0xffff)
574 uint tipId = _Tips.size();
579 _Tips.resize(tipId+1);
580 CTip &tip = _Tips[tipId];
581 tip.Point = (whichTip) ? getStopVector(i) : getStartVector(i);
583 for (turn=0; turn<=1; ++turn)
589 _Chains[chain]._StopTip = tipId;
591 _Chains[chain]._StartTip = tipId;
593 sint32 surf = (!turn && !whichTip || turn && whichTip) ? _Chains[chain].getLeft() : _Chains[chain].getRight();
598 CChain &nextChain = (turn) ? _Chains[chain = getNextChain(chain, surf)] : _Chains[chain = getPreviousChain(chain, surf)];
599 bool isForward = (nextChain.getLeft() == surf); // tells if the left surf is the current surf
600 bool selectTip = isForward && !turn || !isForward && turn;
601 uint16 &tipRef = selectTip ? nextChain._StopTip : nextChain._StartTip;
602 surf = (isForward) ? nextChain.getRight() : nextChain.getLeft();
604 if (tipRef != 0xffff && tipRef != tipId)
606 nlwarning("in NLPACS::CLocalRetriever::computeLoopsAndTips()");
607 nlerror("Trying to setup a already created tip (tipId=%d, previous=%d)", tipId, tipRef);
609 else if (tipRef != 0xffff)
621 for (i=0; i<_Chains.size(); ++i)
623 uint startTip = _Chains[i].getStartTip(),
624 stopTip = _Chains[i].getStopTip();
627 // if (_Chains[i].getEdge() >= 0 && startTip == stopTip)
629 // nlwarning("NLPACS::CLocalRetriever::computeLoopsAndTips(): chain %d on edge %d has same StartTip and StopTip", i, _Chains[i].getEdge(), startTip, stopTip);
633 _Tips[startTip].Chains.push_back(CTip::CChainTip(i, true));
634 _Tips[stopTip].Chains.push_back(CTip::CChainTip(i, false));
637 for (i
=0; i
<_Surfaces
.size(); ++i
)
639 for (j
=0; j
<_Surfaces
[i
]._Loops
.size(); ++j
)
641 _Surfaces
[i
]._Loops
[j
].Length
= 0.0f
;
644 for (k
=0; k
<_Surfaces
[i
]._Loops
[j
].size(); ++k
)
645 _Surfaces
[i
]._Loops
[j
].Length
+= _Chains
[_Surfaces
[i
]._Chains
[_Surfaces
[i
]._Loops
[j
][k
]].Chain
].getLength();
652 void NLPACS::CLocalRetriever::buildSurfacePolygons(uint32 surface
, list
<CPolygon
> &polygons
) const
654 const CRetrievableSurface
&surf
= _Surfaces
[surface
];
658 for (i
=0; i
<surf
._Loops
.size(); ++i
)
660 polygons
.push_back(CPolygon());
661 CPolygon
&poly
= polygons
.back();
663 for (j
=0; j
<surf
._Loops
[i
].size(); ++j
)
665 const CChain
&chain
= _Chains
[surf
._Loops
[i
][j
]];
666 bool chainforward
= ((uint32
)chain
._Left
== surface
);
670 for (k
=0; k
<chain
._SubChains
.size(); ++k
)
672 const COrderedChain
&ochain
= _OrderedChains
[chain
._SubChains
[k
]];
673 bool ochainforward
= ochain
.isForward();
677 for (l
=0; l
<ochain
.getVertices().size()-1; ++l
)
678 poly
.Vertices
.push_back(ochain
[l
].unpack3f());
682 for (l
=(uint
)ochain
.getVertices().size()-1; l
>0; --l
)
683 poly
.Vertices
.push_back(ochain
[l
].unpack3f());
689 for (k
=(uint
)chain
._SubChains
.size(); (sint
)k
>0; --k
)
691 const COrderedChain
&ochain
= _OrderedChains
[chain
._SubChains
[k
]];
692 bool ochainforward
= ochain
.isForward();
696 for (l
=(uint
)ochain
.getVertices().size()-1; (sint
)l
>0; --l
)
697 poly
.Vertices
.push_back(ochain
[l
].unpack3f());
701 for (l
=0; l
<ochain
.getVertices().size()-1; ++l
)
702 poly
.Vertices
.push_back(ochain
[l
].unpack3f());
711 void NLPACS::CLocalRetriever::build3dSurfacePolygons(uint32 surface
, list
<CPolygon
> &polygons
) const
713 const CRetrievableSurface
&surf
= _Surfaces
[surface
];
717 for (i
=0; i
<surf
._Loops
.size(); ++i
)
719 polygons
.push_back(CPolygon());
720 CPolygon
&poly
= polygons
.back();
722 for (j
=0; j
<surf
._Loops
[i
].size(); ++j
)
724 const CRetrievableSurface::TLoop
&loop
= surf
._Loops
[i
];
725 const CChain
&chain
= _Chains
[surf
._Chains
[loop
[j
]].Chain
];
726 bool chainforward
= ((uint32
)chain
._Left
== surface
);
730 for (k
=0; k
<chain
._SubChains
.size(); ++k
)
732 const COrderedChain3f
&ochain
= _FullOrderedChains
[chain
._SubChains
[k
]];
733 bool ochainforward
= ochain
.isForward();
737 for (l
=0; l
<ochain
.getVertices().size()-1; ++l
)
738 poly
.Vertices
.push_back(ochain
[l
]);
742 for (l
=(uint
)ochain
.getVertices().size()-1; l
>0; --l
)
743 poly
.Vertices
.push_back(ochain
[l
]);
749 for (k
=(uint
)chain
._SubChains
.size()-1; (sint
)k
>=0; --k
)
751 const COrderedChain3f
&ochain
= _FullOrderedChains
[chain
._SubChains
[k
]];
752 bool ochainforward
= ochain
.isForward();
756 for (l
=(uint
)ochain
.getVertices().size()-1; (sint
)l
>0; --l
)
757 poly
.Vertices
.push_back(ochain
[l
]);
761 for (l
=0; l
<ochain
.getVertices().size()-1; ++l
)
762 poly
.Vertices
.push_back(ochain
[l
]);
771 // not implemented...
772 void NLPACS::CLocalRetriever::sortTips()
779 void NLPACS::CLocalRetriever::findBorderChains()
783 // for each chain, if it belongs to an edge of the
784 // local retriever, then adds it to the _BorderChains.
785 for (chain
=0; chain
<_Chains
.size(); ++chain
)
786 if (_Chains
[chain
].isBorderChain())
788 sint32 index
= (sint32
)_BorderChains
.size();
789 _BorderChains
.push_back(uint16(chain
));
790 _Chains
[chain
].setBorderChainIndex(index
);
794 void NLPACS::CLocalRetriever::updateChainIds()
798 for (surf
=0; surf
<_Surfaces
.size(); ++surf
)
800 CRetrievableSurface
&surface
= _Surfaces
[surf
];
802 for (link
=0; link
<surface
._Chains
.size(); ++link
)
804 sint32 chain
= surface
._Chains
[link
].Chain
;
806 if (_Chains
[chain
]._Left
== (sint32
)surf
)
807 surface
._Chains
[link
].Surface
= _Chains
[chain
]._Right
;
808 else if (_Chains
[chain
]._Right
== (sint32
)surf
)
809 surface
._Chains
[link
].Surface
= _Chains
[chain
]._Left
;
812 nlwarning("in NLPACS::CLocalRetriever::updateEdgesOnSurfaces()");
813 nlerror("Can't find back point to surface %d on chain %d", surf
, chain
);
819 void NLPACS::CLocalRetriever::computeTopologies()
821 //nlinfo("compute topologies");
823 // Find topologies out...
825 for (character
=0; character
<NumCreatureModels
; ++character
)
827 // for each type of creature, flood fill surfaces...
831 for (surface
=0; surface
<(sint
)_Surfaces
.size(); ++surface
)
833 if (_Surfaces
[surface
]._Topologies
[character
] == -1 &&
834 _Surfaces
[surface
]._Character
== character
)
836 vector
<sint32
> surfacesStack
;
837 surfacesStack
.push_back(surface
);
839 while (!surfacesStack
.empty())
841 CRetrievableSurface
¤t
= _Surfaces
[surfacesStack
.back()];
842 surfacesStack
.pop_back();
843 current
._Topologies
[character
] = topology
;
846 for (i
=0; i
<current
._Chains
.size(); ++i
)
848 CChain
&chain
= _Chains
[current
._Chains
[i
].Chain
];
849 sint32 link
= (chain
.getLeft() == surface
) ? chain
.getRight() : chain
.getLeft();
850 if (link
>=0 && link
<(sint
)_Surfaces
.size() &&
851 _Surfaces
[link
]._Topologies
[character
] == -1 &&
852 _Surfaces
[link
]._Character
>= character
)
854 surfacesStack
.push_back(link
);
855 _Surfaces
[link
]._Topologies
[character
] = topology
;
864 _Topologies
[character
].resize(topology
);
865 //nlinfo("generated %d topologies for character %d", topology, character);
869 for (surface
=0; surface
<_Surfaces
.size(); ++surface
)
871 CRetrievableSurface
¤t
= _Surfaces
[surface
];
873 for (character
=0; character
<NumCreatureModels
; ++character
)
874 if (current
._Topologies
[character
] >= 0)
875 _Topologies
[character
][current
._Topologies
[character
]].push_back(surface
);
879 void NLPACS::CLocalRetriever::translate(const NLMISC::CVector
&translation
)
882 for (i
=0; i
<_OrderedChains
.size(); ++i
)
883 _OrderedChains
[i
].translate(translation
);
884 for (i
=0; i
<_Surfaces
.size(); ++i
)
885 _Surfaces
[i
].translate(translation
);
887 for (i=0; i<_Tips.size(); ++i)
888 _Tips[i].translate(translation);
892 void NLPACS::CLocalRetriever::serial(NLMISC::IStream
&f
)
896 - base version (with collision info).
898 - interior vertices and faces, for interior ground snapping
904 - topologies no more in stream (obsolete)
906 sint ver
= f
.serialVersion(4);
909 throw EOlderStream();
912 f
.serialCont(_Chains
);
913 f
.serialCont(_OrderedChains
);
914 f
.serialCont(_FullOrderedChains
);
915 f
.serialCont(_Surfaces
);
916 f
.serialCont(__Tips
);
917 f
.serialCont(_BorderChains
);
920 for (i
=0; i
<NumMaxCreatureModels
; ++i
)
921 f
.serialCont(_Topologies
[i
]);
923 f
.serial(_ChainQuad
);
926 f
.serial(_ExteriorMesh
);
928 // a fix for old versions (with wrong _Type value)
929 if (_Type
!= CLocalRetriever::Interior
) _Type
= CLocalRetriever::Landscape
;
933 f
.serialCont(_InteriorVertices
);
934 f
.serialCont(_InteriorFaces
);
947 LoadCheckFlag
= false;
957 bool NLPACS::CLocalRetriever::insurePosition(NLPACS::ULocalPosition
&local
) const
962 if (local
.Surface
< 0 || local
.Surface
>= (sint
)_Surfaces
.size())
964 nlwarning("PACS: can't insure position to inexistant surface %d", local
.Surface
);
969 const NLPACS::CRetrievableSurface
&surface
= _Surfaces
[local
.Surface
];
972 CVector2f M
= CVector2f(local
.Estimation
);
975 // for each chain and each subchain of the surface,
976 // check if point is located on the good side of the border (and far enough to avoid accuracy issues)
977 for (i
=0; i
<surface
.getChains().size(); ++i
)
979 uint ichain
= surface
.getChain(i
).Chain
;
980 const NLPACS::CChain
&chain
= _Chains
[ichain
];
982 for (j
=0; j
<chain
.getSubChains().size(); ++j
)
984 uint iochain
= chain
.getSubChain(j
);
985 const NLPACS::COrderedChain
&ochain
= _OrderedChains
[iochain
];
987 uint isAtLeft
= ((chain
.getLeft() == local
.Surface
) ? 1 : 0);
988 uint isForward
= (ochain
.isForward() ? 1 : 0);
989 bool shouldBeUpper
= !((isAtLeft
^ isForward
) != 0); // shouldBeAtLeft for vertical segment
991 for (k
=0; (sint
)k
<(sint
)(ochain
.getVertices().size()-1); ++k
)
993 CVector2f A
= ochain
[k
].unpack();
994 CVector2f B
= ochain
[k
+1].unpack();
997 float lambda
= ((M
-A
)*AB
)/AB
.sqrnorm();
999 if (lambda
<0.0f
|| lambda
>1.0f
)
1002 CVector2f n
= (shouldBeUpper
? CVector2f(-AB
.y
, AB
.x
) : CVector2f(AB
.y
, -AB
.x
)).normed();
1005 // if point is too close of the border or on the wrong side
1006 // move it far enough
1007 if (d
< InsurePositionThreshold
&& d
> -InsurePositionThreshold
)
1009 M
+= (InsurePositionThreshold
*1.1f
-d
)*n
;
1016 NLPACS::CRetrieverInstance::snapVector(M
);
1018 local
.Estimation
.x
= M
.x
;
1019 local
.Estimation
.y
= M
.y
;
1022 float fx1024
= local
.Estimation
.x
* 1024.0f
;
1023 float fy1024
= local
.Estimation
.x
* 1024.0f
;
1024 sint32 ix1024
= (sint32
)floor(fx1024
);
1025 sint32 iy1024
= (sint32
)floor(fy1024
);
1027 nlassert ((float)ix1024
== fx1024
);
1028 nlassert ((float)iy1024
== fy1024
);
1035 bool NLPACS::CLocalRetriever::testPosition(NLPACS::ULocalPosition
&local
, CCollisionSurfaceTemp
&cst
) const
1040 if (local
.Surface
< 0 || local
.Surface
>= (sint
)_Surfaces
.size())
1042 nlwarning("PACS: can't test inexistant surface %d", local
.Surface
);
1046 if (fabs(local
.Estimation
.x
) >= 256.0 || fabs(local
.Estimation
.y
) >= 256.0)
1049 retrievePosition(local
.Estimation
, cst
);
1051 bool result
= (cst
.SurfaceLUT
[local
.Surface
].Counter
== 2 || cst
.SurfaceLUT
[local
.Surface
].OnVerticalEdge
);
1054 for (i
=0; i
<cst
.PossibleSurfaces
.size(); ++i
)
1055 cst
.SurfaceLUT
[cst
.PossibleSurfaces
[i
]].reset();
1061 void NLPACS::CLocalRetriever::retrievePosition(CVector estimated
, CCollisionSurfaceTemp
&cst
) const
1067 const double BorderThreshold
= 2.0e-2f
;
1068 box
.setMinMax(CVector(estimated
.x
-(float)BorderThreshold
, _BBox
.getMin().y
, 0.0f
), CVector(estimated
.x
+(float)BorderThreshold
, _BBox
.getMax().y
, 0.0f
));
1069 uint numEdges
= _ChainQuad
.selectEdges(box
, cst
);
1072 CVector2s estim
= CVector2s(estimated
);
1074 cst
.PossibleSurfaces
.clear();
1077 // cst.SurfaceLUT is assumed to be 0 filled !!
1079 //nldebug("estim=(%d,%d)", estim.x, estim.y);
1081 // for each ordered chain, checks if the estimated position is between the min and max.
1082 for (i
=0; i
<numEdges
; ++i
)
1084 ochain
= cst
.EdgeChainEntries
[i
].OChainId
;
1086 const COrderedChain
&sub
= _OrderedChains
[ochain
];
1087 const CVector2s
&min
= sub
.getMin(),
1088 &max
= sub
.getMax();
1090 // checks the position against the min and max of the chain
1091 if (estim
.x
< min
.x
|| estim
.x
> max
.x
)
1095 bool isOnBorder
= false;
1097 sint32 left
= _Chains
[sub
.getParentId()].getLeft(),
1098 right
= _Chains
[sub
.getParentId()].getRight();
1100 if (estim
.y
< min
.y
)
1102 if (estim
.x
== max
.x
)
1105 // nlinfo("Box: min(%d,%d) max(%d,%d) forward=%d left=%d right=%d upper=false", min.x, min.y, max.x, max.y, sub.isForward(), left, right);
1107 else if (estim
.y
> max
.y
)
1109 if (estim
.x
== max
.x
)
1112 // nlinfo("Box: min(%d,%d) max(%d,%d) forward=%d left=%d right=%d upper=true", min.x, min.y, max.x, max.y, sub.isForward(), left, right);
1116 const vector
<CVector2s
> &vertices
= sub
.getVertices();
1117 uint start
= 0, stop
= (uint
)vertices
.size()-1;
1119 // then finds the smallest segment of the chain that includes the estimated position.
1120 while (stop
-start
> 1)
1122 uint mid
= (start
+stop
)/2;
1124 if (vertices
[mid
].x
> estim
.x
)
1130 // if a vertical edge
1131 if (vertices
[start
].x
== vertices
[stop
].x
)
1133 // look for maximal bounds
1134 while (start
> 0 && vertices
[start
].x
== vertices
[start
-1].x
)
1137 while (stop
< vertices
.size()-1 && vertices
[stop
].x
== vertices
[stop
+1].x
)
1140 // if upper or lower the bounds, do nothing
1141 if ((estim
.y
> vertices
[start
].y
&& estim
.y
> vertices
[stop
].y
) ||
1142 (estim
.y
< vertices
[start
].y
&& estim
.y
< vertices
[stop
].y
))
1148 cst
.SurfaceLUT
[left
].FoundCloseEdge
= true;
1149 cst
.SurfaceLUT
[left
].OnVerticalEdge
= true;
1153 cst
.SurfaceLUT
[right
].FoundCloseEdge
= true;
1154 cst
.SurfaceLUT
[right
].OnVerticalEdge
= true;
1156 // nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d border=true", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
1159 else if (vertices
[stop
].x
== estim
.x
)
1165 // and then checks if the estimated position is up or down the chain.
1167 // first trivial case (up both tips)
1168 if (estim
.y
> vertices
[start
].y
&& estim
.y
> vertices
[stop
].y
)
1171 // nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=true", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
1173 // second trivial case (down both tips)
1174 else if (estim
.y
< vertices
[start
].y
&& estim
.y
< vertices
[stop
].y
)
1177 // nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=false", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right);
1182 const CVector2s
&vstart
= vertices
[start
],
1183 &vstop
= vertices
[stop
];
1185 sint16 intersect
= vstart
.y
+ (vstop
.y
-vstart
.y
)*(estim
.x
-vstart
.x
)/(vstop
.x
-vstart
.x
);
1187 isUpper
= estim
.y
> intersect
;
1188 //isOnBorder = (fabs(estim.y - intersect)<BorderThreshold*Vector2sAccuracy);
1189 isOnBorder
= (fabs((double)(estim
.y
- intersect
))<(double)(BorderThreshold
*Vector2sAccuracy
));
1190 // nlinfo("Edge: start(%d,%d) stop(%d,%d) forward=%d left=%d right=%d upper=%s border=%s", vertices[start].x, vertices[start].y, vertices[stop].x, vertices[stop].y, sub.isForward(), left, right, isUpper ? "true":"false", isOnBorder ? "true":"false");
1196 cst
.incSurface(left
);
1197 cst
.incSurface(right
);
1198 if (left
>= 0) cst
.SurfaceLUT
[left
].FoundCloseEdge
= true;
1199 if (right
>= 0) cst
.SurfaceLUT
[right
].FoundCloseEdge
= true;
1203 // Depending on the chain is forward, up the position, increase/decrease the surface table...
1204 if (sub
.isForward())
1208 cst
.incSurface(left
);
1209 cst
.decSurface(right
);
1213 cst
.decSurface(left
);
1214 cst
.incSurface(right
);
1221 cst
.decSurface(left
);
1222 cst
.incSurface(right
);
1226 cst
.incSurface(left
);
1227 cst
.decSurface(right
);
1234 void NLPACS::CLocalRetriever::retrieveAccuratePosition(CVector2s estim
, CCollisionSurfaceTemp
&cst
, bool &onBorder
) const
1240 CVector estimated
= estim
.unpack3f();
1241 const double BorderThreshold
= 2.0e-2f
;
1242 box
.setMinMax(CVector(estimated
.x
-(float)BorderThreshold
, _BBox
.getMin().y
, 0.0f
),
1243 CVector(estimated
.x
+(float)BorderThreshold
, _BBox
.getMax().y
, 0.0f
));
1244 uint numEdges
= _ChainQuad
.selectEdges(box
, cst
);
1250 cst
.PossibleSurfaces
.clear();
1253 // cst.SurfaceLUT is assumed to be 0 filled !!
1255 //nldebug("estim=(%d,%d)", estim.x, estim.y);
1257 // for each ordered chain, checks if the estimated position is between the min and max.
1258 for (i
=0; i
<numEdges
; ++i
)
1260 ochain
= cst
.EdgeChainEntries
[i
].OChainId
;
1262 const COrderedChain
&sub
= _OrderedChains
[ochain
];
1263 const CVector2s
&min
= sub
.getMin(),
1264 &max
= sub
.getMax();
1266 // checks the position against the min and max of the chain
1267 if (estim
.x
< min
.x
|| estim
.x
> max
.x
)
1271 //bool isOnBorder = false;
1273 sint32 left
= _Chains
[sub
.getParentId()].getLeft(),
1274 right
= _Chains
[sub
.getParentId()].getRight();
1276 if (estim
.y
< min
.y
)
1278 if (estim
.x
== max
.x
)
1282 else if (estim
.y
> max
.y
)
1284 if (estim
.x
== max
.x
)
1290 const vector
<CVector2s
> &vertices
= sub
.getVertices();
1291 uint start
= 0, stop
= (uint
)vertices
.size()-1;
1293 // then finds the smallest segment of the chain that includes the estimated position.
1294 while (stop
-start
> 1)
1296 uint mid
= (start
+stop
)/2;
1298 if (vertices
[mid
].x
> estim
.x
)
1304 // if a vertical edge
1305 if (vertices
[start
].x
== vertices
[stop
].x
)
1307 // look for maximal bounds
1308 while (start
> 0 && vertices
[start
].x
== vertices
[start
-1].x
)
1311 while (stop
< vertices
.size()-1 && vertices
[stop
].x
== vertices
[stop
+1].x
)
1314 // if upper or lower the bounds, do nothing
1315 if ((estim
.y
> vertices
[start
].y
&& estim
.y
> vertices
[stop
].y
) ||
1316 (estim
.y
< vertices
[start
].y
&& estim
.y
< vertices
[stop
].y
))
1322 else if (vertices
[stop
].x
== estim
.x
)
1328 // and then checks if the estimated position is up or down the chain.
1330 // first trivial case (up both tips)
1331 if (estim
.y
> vertices
[start
].y
&& estim
.y
> vertices
[stop
].y
)
1335 // second trivial case (down both tips)
1336 else if (estim
.y
< vertices
[start
].y
&& estim
.y
< vertices
[stop
].y
)
1343 const CVector2s
&vstart
= vertices
[start
],
1344 &vstop
= vertices
[stop
];
1346 // this test is somewhat more accurate
1347 // no division performed
1348 sint32 det
= (estim
.y
-vstart
.y
)*(vstop
.x
-vstart
.x
) - (estim
.x
-vstart
.x
)*(vstop
.y
-vstart
.y
);
1350 isUpper
= (det
> 0);
1357 // Depending on the chain is forward, up the position, increase/decrease the surface table...
1358 if (sub
.isForward())
1362 cst
.incSurface(left
);
1363 cst
.decSurface(right
);
1367 cst
.decSurface(left
);
1368 cst
.incSurface(right
);
1375 cst
.decSurface(left
);
1376 cst
.incSurface(right
);
1380 cst
.incSurface(left
);
1381 cst
.decSurface(right
);
1389 void NLPACS::CLocalRetriever::initFaceGrid()
1391 CFaceGrid::CFaceGridBuild fgb
;
1395 for (i
=0; i
<_InteriorFaces
.size(); ++i
)
1398 CInteriorFace
&f
= _InteriorFaces
[i
];
1399 box
.setCenter(_InteriorVertices
[f
.Verts
[0]]);
1400 box
.extend(_InteriorVertices
[f
.Verts
[1]]);
1401 box
.extend(_InteriorVertices
[f
.Verts
[2]]);
1403 fgb
.insert(box
.getMin(), box
.getMax(), i
);
1406 _FaceGrid
.create(fgb
);
1409 void NLPACS::CLocalRetriever::snapToInteriorGround(NLPACS::ULocalPosition
&position
, bool &snapped
) const
1414 // first preselect faces around the (x, y) position (CQuadGrid ?)
1415 vector
<uint32
> selection
;
1416 _FaceGrid
.select(position
.Estimation
, selection
);
1418 // from the preselect faces, look for the only face that belongs to the surface
1419 // and that contains the position
1420 CVector pos
= position
.Estimation
;
1421 CVector posh
= pos
+CVector(0.0f
, 0.0f
, 1.0f
);
1422 CVector2f pos2d
= position
.Estimation
;
1423 float bestDist
= 1.0e10f
;
1424 CVector
best(0.0f
, 0.0f
, 0.0f
);
1425 vector
<uint32
>::iterator it
;
1427 for (it
=selection
.begin(); it
!=selection
.end(); ++it
)
1429 const CInteriorFace
&f
= _InteriorFaces
[*it
];
1430 if (f
.Surface
== (uint32
)position
.Surface
)
1433 v
[0] = _InteriorVertices
[f
.Verts
[0]];
1434 v
[1] = _InteriorVertices
[f
.Verts
[1]];
1435 v
[2] = _InteriorVertices
[f
.Verts
[2]];
1438 float c
; // 2D cartesian coefficients of line in plane X/Y.
1440 n
= CVector2f(-(v
[1].y
-v
[0].y
), (v
[1].x
-v
[0].x
)).normed();
1441 c
= -(v
[0].x
*n
.x
+ v
[0].y
*n
.y
);
1442 if (n
*pos2d
+ c
< -1.0f
/Vector2sAccuracy
) continue;
1444 n
= CVector2f(-(v
[2].y
-v
[1].y
), (v
[2].x
-v
[1].x
)).normed();
1445 c
= -(v
[1].x
*n
.x
+ v
[1].y
*n
.y
);
1446 if (n
*pos2d
+ c
< -1.0f
/Vector2sAccuracy
) continue;
1448 n
= CVector2f(-(v
[0].y
-v
[2].y
), (v
[0].x
-v
[2].x
)).normed();
1449 c
= -(v
[2].x
*n
.x
+ v
[2].y
*n
.y
);
1450 if (n
*pos2d
+ c
< -1.0f
/Vector2sAccuracy
) continue;
1453 p
.make(v
[0], v
[1], v
[2]);
1455 CVector i
= p
.intersect(pos
, posh
);
1457 float d
= (float)fabs(pos
.z
-i
.z
);
1467 // and computes the real position on this face
1468 if (bestDist
< 400.0f
)
1471 position
.Estimation
= best
;
1475 // ***************************************************************************
1476 float NLPACS::CLocalRetriever::getHeight(const NLPACS::ULocalPosition
&position
) const
1481 if (_Type
== Interior
)
1483 // first preselect faces around the (x, y) position (CQuadGrid ?)
1484 vector
<uint32
> selection
;
1485 _FaceGrid
.select(position
.Estimation
, selection
);
1487 // from the preselect faces, look for the only face that belongs to the surface
1488 // and that contains the position
1489 CVector pos
= position
.Estimation
;
1490 CVector posh
= pos
+CVector(0.0f
, 0.0f
, 1.0f
);
1491 float bestDist
= 1.0e10f
;
1492 CVector
best(0.0f
, 0.0f
, 0.0f
);
1493 vector
<uint32
>::iterator it
;
1494 for (it
=selection
.begin(); it
!=selection
.end(); ++it
)
1496 const CInteriorFace
&f
= _InteriorFaces
[*it
];
1497 if (f
.Surface
== (uint32
)position
.Surface
)
1500 v
[0] = _InteriorVertices
[f
.Verts
[0]];
1501 v
[1] = _InteriorVertices
[f
.Verts
[1]];
1502 v
[2] = _InteriorVertices
[f
.Verts
[2]];
1504 float a
,b
,c
; // 2D cartesian coefficients of line in plane X/Y.
1506 a
= -(v
[1].y
-v
[0].y
);
1507 b
= (v
[1].x
-v
[0].x
);
1508 c
= -(v
[0].x
*a
+ v
[0].y
*b
);
1509 if (a
*pos
.x
+ b
*pos
.y
+ c
< 0) continue;
1511 a
= -(v
[2].y
-v
[1].y
);
1512 b
= (v
[2].x
-v
[1].x
);
1513 c
= -(v
[1].x
*a
+ v
[1].y
*b
);
1514 if (a
*pos
.x
+ b
*pos
.y
+ c
< 0) continue;
1516 a
= -(v
[0].y
-v
[2].y
);
1517 b
= (v
[0].x
-v
[2].x
);
1518 c
= -(v
[2].x
*a
+ v
[2].y
*b
);
1519 if (a
*pos
.x
+ b
*pos
.y
+ c
< 0) continue;
1522 p
.make(v
[0], v
[1], v
[2]);
1524 CVector i
= p
.intersect(pos
, posh
);
1526 float d
= (float)fabs(pos
.z
-i
.z
);
1536 // and computes the real position on this face
1537 return (bestDist
< 200.0f
) ? best
.z
: position
.Estimation
.z
;
1541 if (_Surfaces
[position
.Surface
].getQuadTree().getRoot() != NULL
)
1544 const CQuadLeaf
*leaf
= _Surfaces
[position
.Surface
].getQuadTree().getLeaf(position
.Estimation
);
1546 // if there is no acceptable leaf, just give up
1549 //nlinfo("COL: quadtree: don't find the quadLeaf!");
1550 return position
.Estimation
.z
;
1554 // else return mean height.
1555 float meanHeight
= (leaf
->getMinHeight()+leaf
->getMaxHeight())*0.5f
;
1559 else if (_Surfaces
[position
.Surface
].isUnderWater())
1561 return _Surfaces
[position
.Surface
].getWaterHeight();
1565 sint8 qh
= _Surfaces
[position
.Surface
].getQuantHeight();
1566 return qh
*2.0f
+ 1.0f
;
1572 // ***************************************************************************
1573 float NLPACS::CLocalRetriever::getInteriorHeightAround(const ULocalPosition
&position
, float outsideTolerance
) const
1578 if (_Type
== Interior
)
1580 // first preselect faces around the (x, y) position (CQuadGrid ?)
1581 vector
<uint32
> selection
;
1582 _FaceGrid
.select(position
.Estimation
, selection
);
1584 // from the preselect faces, look for the only face that belongs to the surface
1585 // and that contains the position
1586 CVector pos
= position
.Estimation
;
1587 CVector posh
= pos
+CVector(0.0f
, 0.0f
, 1.0f
);
1588 float bestDist
= 1.0e10f
;
1589 CVector
best(0.0f
, 0.0f
, 0.0f
);
1590 vector
<uint32
>::iterator it
;
1591 for (it
=selection
.begin(); it
!=selection
.end(); ++it
)
1593 const CInteriorFace
&f
= _InteriorFaces
[*it
];
1594 if (f
.Surface
== (uint32
)position
.Surface
)
1597 v
[0] = _InteriorVertices
[f
.Verts
[0]];
1598 v
[1] = _InteriorVertices
[f
.Verts
[1]];
1599 v
[2] = _InteriorVertices
[f
.Verts
[2]];
1601 // Test if out of this triangle (+ tolerance)
1602 float a
,b
; // 2D cartesian coefficients of line in plane X/Y.
1605 a
= -(v
[1].y
-v
[0].y
);
1606 b
= (v
[1].x
-v
[0].x
);
1607 len
= sqrtf(a
*a
+b
*b
); // norm of the normal vector
1608 if (a
*(pos
.x
-v
[0].x
) + b
*(pos
.y
-v
[0].y
) < -len
*outsideTolerance
) continue;
1610 a
= -(v
[2].y
-v
[1].y
);
1611 b
= (v
[2].x
-v
[1].x
);
1612 len
= sqrtf(a
*a
+b
*b
); // norm of the normal vector
1613 if (a
*(pos
.x
-v
[1].x
) + b
*(pos
.y
-v
[1].y
) < -len
*outsideTolerance
) continue;
1615 a
= -(v
[0].y
-v
[2].y
);
1616 b
= (v
[0].x
-v
[2].x
);
1617 len
= sqrtf(a
*a
+b
*b
); // norm of the normal vector
1618 if (a
*(pos
.x
-v
[2].x
) + b
*(pos
.y
-v
[2].y
) < -len
*outsideTolerance
) continue;
1621 // Ok IN => compute z and keep nearest to wanted one
1623 p
.make(v
[0], v
[1], v
[2]);
1625 CVector i
= p
.intersect(pos
, posh
);
1627 float d
= (float)fabs(pos
.z
-i
.z
);
1637 // and computes the real position on this face
1638 return (bestDist
< 200.0f
) ? best
.z
: position
.Estimation
.z
;
1645 // ***************************************************************************
1646 #ifdef NL_OS_WINDOWS
1647 //#pragma optimize( "", off )
1648 #endif // NL_OS_WINDOWS
1650 void NLPACS::CLocalRetriever::findPath(const NLPACS::CLocalRetriever::CLocalPosition
&A
,
1651 const NLPACS::CLocalRetriever::CLocalPosition
&B
,
1652 std::vector
<NLPACS::CVector2s
> &path
,
1653 NLPACS::CCollisionSurfaceTemp
&cst
) const
1655 if (A
.Surface
!= B
.Surface
)
1657 nlwarning("in NLPACS::CLocalRetriever::findPath()");
1658 nlerror("Try to find a path between 2 points that are not in the same surface (A=%d, B=%d)", A
.Surface
, B
.Surface
);
1661 CVector a
= A
.Estimation
,
1663 n
= CVector(a
.y
-b
.y
, b
.x
-a
.x
, 0.0f
);
1665 _ChainQuad
.selectEdges(a
, b
, cst
);
1667 vector
<CIntersectionMarker
> intersections
;
1670 sint32 surfaceId
= A
.Surface
;
1671 const CRetrievableSurface
&surface
= _Surfaces
[surfaceId
];
1673 for (i
=0; i
<cst
.EdgeChainEntries
.size(); ++i
)
1675 CEdgeChainEntry
&entry
= cst
.EdgeChainEntries
[i
];
1676 const COrderedChain
&chain
= _OrderedChains
[entry
.OChainId
];
1678 if (_Chains
[chain
.getParentId()].getLeft() != surfaceId
&&
1679 _Chains
[chain
.getParentId()].getRight() != surfaceId
)
1682 for (j
=entry
.EdgeStart
; j
<entry
.EdgeEnd
; ++j
)
1684 // here the edge collision test
1686 CVector p0
= chain
[j
].unpack3f(),
1687 p1
= chain
[j
+1].unpack3f();
1689 float vp0
= (p0
-a
)*n
,
1692 if (vp0
*vp1
<= 0.0f
)
1694 CVector np
= CVector(p0
.y
-p1
.y
, p1
.x
-p0
.x
, 0.0f
);
1696 float va
= (a
-p0
)*np
,
1699 // here we have an intersection
1702 const CChain
&parent
= _Chains
[chain
.getParentId()];
1703 bool isIn
= (va
-vb
< 0.0f
) ^ (parent
.getLeft() == surfaceId
) ^ chain
.isForward();
1705 intersections
.push_back(CIntersectionMarker(va
/(va
-vb
), entry
.OChainId
, uint16(j
), isIn
));
1711 sort(intersections
.begin(), intersections
.end());
1713 uint intersStart
= 0;
1714 uint intersEnd
= (uint
)intersections
.size();
1718 while (intersStart
< intersections
.size() &&
1719 intersections
[intersStart
].In
&& intersections
[intersStart
].Position
< 1.0e-4f
)
1722 while (intersStart
< intersEnd
&&
1723 !intersections
[intersEnd
-1].In
&& intersections
[intersEnd
-1].Position
> 1.0f
-1.0e-4f
)
1726 // Check intersections have a valid order
1727 if ((intersEnd
-intersStart
) & 1)
1729 nlwarning("in NLPACS::CLocalRetriever::findPath()");
1730 nlerror("Found an odd (%d) number of intersections", intersections
.size());
1733 for (i
=intersStart
; i
<intersEnd
; )
1735 uint exitLoop
, enterLoop
;
1737 const CChain
&exitChain
= _Chains
[_OrderedChains
[intersections
[i
].OChain
].getParentId()];
1738 exitLoop
= (exitChain
.getLeft() == surfaceId
) ? exitChain
.getLeftLoop() : exitChain
.getRightLoop();
1740 if (intersections
[i
++].In
)
1742 nlwarning("in NLPACS::CLocalRetriever::findPath()");
1743 nlerror("Entered the surface before exited", intersections
.size());
1746 const CChain
&enterChain
= _Chains
[_OrderedChains
[intersections
[i
].OChain
].getParentId()];
1747 enterLoop
= (enterChain
.getLeft() == surfaceId
) ? enterChain
.getLeftLoop() : enterChain
.getRightLoop();
1749 if (!intersections
[i
++].In
)
1751 nlwarning("in NLPACS::CLocalRetriever::findPath()");
1752 nlerror("Exited twice the surface", intersections
.size());
1755 if (exitLoop
!= enterLoop
)
1757 nlwarning("in NLPACS::CLocalRetriever::findPath()");
1758 nlerror("Exited and rentered by a different loop");
1763 // dumpSurface(surfaceId);
1765 path
.push_back(CVector2s(A
.Estimation
));
1767 for (i
=intersStart
; i
<intersEnd
; )
1769 uint exitChainId
= _OrderedChains
[intersections
[i
].OChain
].getParentId(),
1770 enterChainId
= _OrderedChains
[intersections
[i
+1].OChain
].getParentId();
1771 const CChain
&exitChain
= _Chains
[exitChainId
],
1772 &enterChain
= _Chains
[enterChainId
];
1773 uint loopId
, exitLoopIndex
, enterLoopIndex
;
1775 if (exitChain
.getLeft() == surfaceId
)
1777 loopId
= exitChain
.getLeftLoop();
1778 exitLoopIndex
= exitChain
.getLeftLoopIndex();
1782 loopId
= exitChain
.getRightLoop();
1783 exitLoopIndex
= exitChain
.getRightLoopIndex();
1786 const CRetrievableSurface::TLoop
&loop
= surface
._Loops
[loopId
];
1788 if (enterChain
.getLeft() == surfaceId
)
1789 enterLoopIndex
= enterChain
.getLeftLoopIndex();
1791 enterLoopIndex
= enterChain
.getRightLoopIndex();
1793 float forwardLength
= (exitChain
.getLength()+enterChain
.getLength())*0.5f
;
1795 sint loopIndex
= exitLoopIndex
;
1796 uint thisChainId
= exitChainId
;
1797 bool thisChainForward
= (enterChain
.getLeft() == surfaceId
);
1798 uint thisOChainId
= intersections
[i
].OChain
;
1799 sint thisOChainIndex
= _OrderedChains
[thisOChainId
].getIndexInParent();
1802 if (exitChainId
!= enterChainId
)
1804 for (j
=(exitLoopIndex
+1)%loop
.size(); j
!=enterLoopIndex
; j
=(j
+1)%loop
.size())
1805 forwardLength
+= _Chains
[surface
._Chains
[loop
[j
]].Chain
].getLength();
1806 forward
= (forwardLength
<= loop
.Length
-forwardLength
);
1810 forward
= !thisChainForward
^ (_OrderedChains
[intersections
[i
].OChain
].getIndexInParent() < _OrderedChains
[intersections
[i
+1].OChain
].getIndexInParent());
1813 path
.push_back(CVector2s(A
.Estimation
+intersections
[i
].Position
*(B
.Estimation
-A
.Estimation
)));
1817 sint from
= (thisOChainId
== intersections
[i
].OChain
) ? intersections
[i
].Edge
: -1,
1818 to
= (thisOChainId
== intersections
[i
+1].OChain
) ? intersections
[i
+1].Edge
: -1;
1819 bool oforward
= thisChainForward
^ forward
^ _OrderedChains
[thisOChainId
].isForward();
1821 if (from
!= -1 && to
!= -1)
1822 oforward
= (intersections
[i
].Edge
< intersections
[i
+1].Edge
);
1824 _OrderedChains
[thisOChainId
].traverse(from
, to
, oforward
, path
);
1826 if (thisOChainId
== intersections
[i
+1].OChain
)
1829 thisOChainIndex
= (thisChainForward
^ forward
) ? thisOChainIndex
-1 : thisOChainIndex
+1;
1831 if (thisOChainIndex
< 0 || thisOChainIndex
>= (sint
)_Chains
[thisChainId
]._SubChains
.size())
1836 if (loopIndex
== (sint
)loop
.size())
1843 loopIndex
= (sint
)loop
.size()-1;
1846 thisChainId
= surface
._Chains
[loop
[loopIndex
]].Chain
;
1847 thisChainForward
= (_Chains
[thisChainId
].getLeft() == surfaceId
);
1848 thisOChainIndex
= (thisChainForward
== forward
) ?
1849 0 : (sint
)_Chains
[thisChainId
]._SubChains
.size()-1;
1852 thisOChainId
= _Chains
[thisChainId
]._SubChains
[thisOChainIndex
];
1855 path
.push_back(CVector2s(A
.Estimation
+intersections
[i
+1].Position
*(B
.Estimation
-A
.Estimation
)));
1859 path
.push_back(CVector2s(B
.Estimation
));
1861 #ifdef NL_OS_WINDOWS
1862 //#pragma optimize( "", on )
1863 #endif // NL_OS_WINDOWS
1865 // ***************************************************************************
1866 // ***************************************************************************
1868 // ***************************************************************************
1869 // ***************************************************************************
1872 // ***************************************************************************
1873 void NLPACS::CLocalRetriever::computeCollisionChainQuad()
1875 _ChainQuad
.build(_OrderedChains
);
1879 // ***************************************************************************
1880 void NLPACS::CLocalRetriever::testCollision(CCollisionSurfaceTemp
&cst
, const CAABBox
&bboxMove
, const CVector2f
&transBase
) const
1885 // H_AUTO(PACS_LR_testCollision);
1889 // 0. select ordered chains in the chainquad.
1890 //=====================================
1891 // H_BEFORE(PACS_LR_testCol_selEdges);
1892 sint nEce
= _ChainQuad
.selectEdges(bboxMove
, cst
);
1893 // H_AFTER(PACS_LR_testCol_selEdges);
1894 // NB: cst.OChainLUT is assured to be full of 0xFFFF after this call (if was right before).
1897 // 1. regroup them in chains. build cst.CollisionChains
1898 //=====================================
1899 // NB: use cst.OChainLUT to look if a Chain has been inserted before.
1900 uint16
*chainLUT
= cst
.OChainLUT
;
1902 // bkup where we begin to add chains.
1903 uint firstChainAdded
= (uint
)cst
.CollisionChains
.size();
1905 // For all edgechain entry.
1908 CEdgeChainEntry
&ece
= cst
.EdgeChainEntries
[i
];
1909 // this is the ordered chain in the retriever.
1910 const COrderedChain
&oChain
= this->getOrderedChains()[ece
.OChainId
];
1911 // this is the id of the chain is the local retriever.
1912 uint16 chainId
= oChain
.getParentId();
1914 // test if edge is interior and points to another instance
1915 if (_Type
== Interior
&& CChain::isBorderChainId(this->getChains()[chainId
].getRight()))
1917 // then look for a door that match this edge
1919 for (l
=0; l
<_ExteriorMesh
.getLinks().size() && _ExteriorMesh
.getLink(l
).ChainId
!= chainId
; ++l
)
1922 // if found a door, then leave the edge as is
1923 if (l
< _ExteriorMesh
.getLinks().size())
1928 // add/retrieve the id in cst.CollisionChains.
1929 //=================================
1932 if(chainLUT
[chainId
]==0xFFFF)
1934 // H_AUTO(PACS_LR_testCol_addToLUT);
1935 // add a new CCollisionChain.
1936 ccId
= (uint
)cst
.CollisionChains
.size();
1937 cst
.CollisionChains
.push_back(CCollisionChain());
1938 // Fill it with default.
1939 cst
.CollisionChains
[ccId
].Tested
= false;
1940 cst
.CollisionChains
[ccId
].ExteriorEdge
= false;
1941 cst
.CollisionChains
[ccId
].FirstEdgeCollide
= 0xFFFFFFFF;
1942 cst
.CollisionChains
[ccId
].ChainId
= chainId
;
1943 // Fill Left right info.
1944 cst
.CollisionChains
[ccId
].LeftSurface
.SurfaceId
= this->getChains()[chainId
].getLeft();
1945 cst
.CollisionChains
[ccId
].RightSurface
.SurfaceId
= this->getChains()[chainId
].getRight();
1946 // NB: cst.CollisionChains[ccId].*Surface.RetrieverInstanceId is not filled here because we don't have
1947 // this info at this level.
1949 // store this Id in the LUT of chains.
1950 chainLUT
[chainId
]= uint16(ccId
);
1954 // get the id of this collision chain.
1955 ccId
= chainLUT
[chainId
];
1958 // add edge collide to the list.
1959 //=================================
1960 // H_BEFORE(PACS_LR_testCol_addToList);
1961 CCollisionChain
&colChain
= cst
.CollisionChains
[ccId
];
1962 const std::vector
<CVector2s
> &oChainVertices
= oChain
.getVertices();
1963 for(sint edge
=ece
.EdgeStart
; edge
<ece
.EdgeEnd
; edge
++)
1965 CVector2f p0
= oChainVertices
[edge
].unpack();
1966 CVector2f p1
= oChainVertices
[edge
+1].unpack();
1968 // alloc a new edgeCollide.
1969 uint32 ecnId
= cst
.allocEdgeCollideNode();
1970 CEdgeCollideNode
&ecn
= cst
.getEdgeCollideNode(ecnId
);
1972 // append to the front of the list.
1973 ecn
.Next
= colChain
.FirstEdgeCollide
;
1974 colChain
.FirstEdgeCollide
= ecnId
;
1981 // H_AFTER(PACS_LR_testCol_addToList);
1986 // 2. Reset LUT to 0xFFFF.
1987 //=====================================
1989 // H_BEFORE(PACS_LR_testCol_resetLUT);
1990 // for all collisions chains inserted (starting from firstChainAdded), reset LUT.
1991 for(i
=firstChainAdded
; i
<(sint
)cst
.CollisionChains
.size(); i
++)
1993 uint ccId
= cst
.CollisionChains
[i
].ChainId
;
1994 chainLUT
[ccId
]= 0xFFFF;
1996 // H_AFTER(PACS_LR_testCol_resetLUT);
2000 // ***************************************************************************
2001 // ***************************************************************************
2002 // ***************************************************************************
2003 // ***************************************************************************
2006 // ***************************************************************************
2007 void NLPACS::CLocalRetriever::buildInteriorSurfaceBBoxes(std::vector
<NLMISC::CAABBox
> &surfaceBBoxes
) const
2009 // resize dest, and init.
2010 vector
<bool> firstTriangle
;
2011 surfaceBBoxes
.clear();
2012 surfaceBBoxes
.resize(_Surfaces
.size());
2013 firstTriangle
.resize(_Surfaces
.size(), true);
2015 // For all _InteriorFaces.
2016 for(uint iIntFace
=0; iIntFace
<_InteriorFaces
.size(); iIntFace
++)
2018 const CInteriorFace
&intFace
= _InteriorFaces
[iIntFace
];
2020 // Extend the surface of this face with her 3 points.
2023 if(intFace
.Surface
==(uint
)-1)
2025 nlassert(intFace
.Surface
<_Surfaces
.size());
2027 // If first time we extend the bbox of this surface
2028 if(firstTriangle
[intFace
.Surface
])
2030 surfaceBBoxes
[intFace
.Surface
].setCenter(_InteriorVertices
[intFace
.Verts
[0]] );
2031 firstTriangle
[intFace
.Surface
]= false;
2034 surfaceBBoxes
[intFace
.Surface
].extend(_InteriorVertices
[intFace
.Verts
[0]] );
2036 // extend with other 2 points
2037 surfaceBBoxes
[intFace
.Surface
].extend(_InteriorVertices
[intFace
.Verts
[1]] );
2038 surfaceBBoxes
[intFace
.Surface
].extend(_InteriorVertices
[intFace
.Verts
[2]] );
2044 // ***************************************************************************
2045 void NLPACS::CLocalRetriever::replaceChain(uint32 chainId
, const std::vector
<NLPACS::CLocalRetriever::CChainReplacement
> &replacement
)
2049 for (i
=0; i
<_Chains
[chainId
]._SubChains
.size(); ++i
)
2051 FreeOChains
.push_back(_Chains
[chainId
]._SubChains
[i
]);
2052 _OrderedChains
[_Chains
[chainId
]._SubChains
[i
]] = COrderedChain();
2053 _FullOrderedChains
[_Chains
[chainId
]._SubChains
[i
]] = COrderedChain3f();
2056 // create new chains in replacement of this chain
2058 for (i
=0; i
<replacement
.size(); ++i
)
2060 vector
<CVector
> vertices
= replacement
[i
].Vertices
;
2061 sint left
= replacement
[i
].Left
;
2062 sint right
= replacement
[i
].Right
;
2064 if (CChain::isBorderChainId(right
))
2066 // check border already exists for this particular chain
2067 sint32 border
= CChain::convertBorderChainId(right
);
2069 if (border
< (sint
)_BorderChains
.size() && (chainId
!= _BorderChains
[border
] || chainId
!= replacement
[i
].Chain
))
2071 nlwarning("replaceChain(): replacement of a border is forced whereas this border is already used and not replaced!");
2074 if (border
>= (sint
)_BorderChains
.size())
2076 if (border
> (sint
)_BorderChains
.size())
2078 nlwarning("replaceChain(): _BorderChains size increased of more than 1 step, holes may result!");
2081 _BorderChains
.resize(border
+1, 0xffff);
2084 _BorderChains
[border
] = uint16(replacement
[i
].Chain
);
2087 nlassert(vertices
.size() >= 2);
2089 // Remove doubled vertices due to CVector2s snapping
2090 vector
<CVector2s
> converts
;
2092 for (j
=0; j
<vertices
.size(); ++j
)
2093 converts
.push_back(CVector2s(vertices
[j
]));
2095 vector
<CVector2s
>::iterator next2s
= converts
.begin(), it2s
, prev2s
;
2096 prev2s
= next2s
; ++next2s
;
2097 it2s
= next2s
; ++next2s
;
2099 vector
<CVector
>::iterator it3f
= vertices
.begin();
2100 CVector prev3f
= *it3f
;
2104 for (; it2s
!= converts
.end() && next2s
!= converts
.end(); )
2106 // if the next point is equal to the previous
2107 if (*it2s
== *prev2s
|| *it2s
== *next2s
)
2109 // then remove the next point
2110 it2s
= converts
.erase(it2s
);
2111 it3f
= vertices
.erase(it3f
);
2120 // else remember the next point, and step to the next...
2129 nlassert(vertices
.size() >= 2);
2131 sint32 newId
= replacement
[i
].Chain
;
2132 if (newId
>= (sint
)_Chains
.size())
2133 _Chains
.resize(newId
+1);
2135 //CChain &nchain = _Chains[newId];
2137 if (left
>(sint
)_Surfaces
.size())
2138 nlerror ("left surface id MUST be id<%d (id=%d)", _Surfaces
.size(), left
);
2139 if (right
>(sint
)_Surfaces
.size())
2140 nlerror ("right surface id MUST be id<%d (id=%d)", _Surfaces
.size(), right
);
2142 // checks if we can build the chain.
2144 nlerror("in NLPACS::CLocalRetriever::addChain(): reached the maximum number of chains");
2146 //CRetrievableSurface *leftSurface = (left>=0) ? &(_Surfaces[left]) : NULL;
2147 //CRetrievableSurface *rightSurface = (right>=0) ? &(_Surfaces[right]) : NULL;
2149 CChain
&chain
= _Chains
[newId
];
2151 chain
._StartTip
= 0xffff;
2152 chain
._StopTip
= 0xffff;
2154 // make the chain and its subchains.
2155 chain
.make(vertices
, left
, right
, _OrderedChains
, (uint16
)newId
, _FullOrderedChains
, FreeOChains
);
2158 for (i
=0; i
<_Surfaces
.size(); ++i
)
2160 // remove old chain and replace by new chains in surface links
2161 for (j
=0; j
<_Surfaces
[i
]._Chains
.size(); ++j
)
2163 if (_Surfaces
[i
]._Chains
[j
].Chain
== (sint
)chainId
)
2165 _Surfaces
[i
]._Chains
.erase(_Surfaces
[i
]._Chains
.begin()+j
);
2168 for (k
=0; k
<replacement
.size(); ++k
)
2170 CRetrievableSurface::CSurfaceLink link
;
2172 link
.Chain
= replacement
[k
].Chain
;
2173 link
.Surface
= (replacement
[k
].Left
== (sint
)i
? replacement
[k
].Right
: replacement
[k
].Left
);
2174 _Surfaces
[i
]._Chains
.push_back(link
);
2181 // remove old chain and replace by new chains in surface loops
2182 for (j
=0; j
<_Surfaces
[i
]._Loops
.size(); ++j
)
2186 for (k
=0; k
<_Surfaces
[i
]._Loops
[j
].size(); ++k
)
2188 if (_Surfaces
[i
]._Loops
[j
][k
] == chainId
)
2190 _Surfaces
[i
]._Loops
[j
].erase(_Surfaces
[i
]._Loops
[j
].begin()+k
);
2193 for (m
=0; m
<replacement
.size(); ++m
)
2194 _Surfaces
[i
]._Loops
[j
].insert(_Surfaces
[i
]._Loops
[j
].begin()+k
+m
, uint16(replacement
[m
].Chain
));
2207 * Check surface integrity
2209 bool NLPACS::CLocalRetriever::checkSurfacesIntegrity(NLMISC::CVector translation
, bool verbose
) const
2211 bool success
= true;
2214 for (surf
=0; surf
<_Surfaces
.size(); ++surf
)
2216 if (!checkSurfaceIntegrity(surf
, translation
, verbose
))
2221 dumpSurface(surf
, translation
);
2232 * Check surface integrity
2234 bool NLPACS::CLocalRetriever::checkSurfaceIntegrity(uint surf
, NLMISC::CVector translation
, bool verbose
) const
2236 if (surf
>= _Surfaces
.size())
2239 const CRetrievableSurface
& surface
= _Surfaces
[surf
];
2241 uint nloops
= (uint
)surface
.getLoops().size();
2243 std::vector
<std::pair
<CVector2s
, CVector2s
> > edges
;
2247 for (iloop
=0; iloop
<nloops
; ++iloop
)
2249 const CRetrievableSurface::TLoop
& loop
= surface
.getLoop(iloop
);
2251 for (i
=0; i
<loop
.size(); ++i
)
2253 // loop[i] is the index in the surface list of chains
2254 // so surface._Chains[loop[i]].Chain is really the chain id !!!
2255 const CChain
& chain
= _Chains
[ surface
._Chains
[loop
[i
]].Chain
];
2256 for (j
=0; j
<chain
.getSubChains().size(); ++j
)
2258 const COrderedChain
& ochain
= _OrderedChains
[chain
.getSubChain(j
)];
2260 for (k
=0; k
+1<ochain
.getVertices().size(); ++k
)
2262 edges
.push_back(std::pair
<CVector2s
, CVector2s
>(ochain
[k
], ochain
[k
+1]));
2268 bool success
= true;
2270 for (i
=0; i
+1<edges
.size(); ++i
)
2272 for (j
=i
+1; j
<edges
.size(); ++j
)
2274 CVector2s a0
= edges
[i
].first
,
2275 a1
= edges
[i
].second
;
2276 CVector2s b0
= edges
[j
].first
,
2277 b1
= edges
[j
].second
;
2280 bool inters
= CVector2s::intersect(a0
, a1
, b0
, b1
, &a
, &b
);
2285 double da
= (a1
-a0
).norm();
2286 double db
= (b1
-b0
).norm();
2288 bool tipa
= (fabs(a
)*da
< 4.0e-2 || fabs(1.0-a
)*da
< 4.0e-2);
2289 bool tipb
= (fabs(b
)*db
< 4.0e-2 || fabs(1.0-b
)*db
< 4.0e-2);
2294 CVector2s ip
= a0
+ (a1
-a0
)*(float)a
;
2295 CVector p
= ip
.unpack3f() - translation
;
2296 nlwarning("Surface %d has issue at position (%f,%f)", surf
, p
.x
, p
.y
);
2300 v
= a0
.unpack3f() - translation
;
2301 nlwarning(" -- a0: (%f,%f)", v
.x
, v
.y
);
2302 v
= a1
.unpack3f() - translation
;
2303 nlwarning(" -- a1: (%f,%f)", v
.x
, v
.y
);
2304 v
= b0
.unpack3f() - translation
;
2305 nlwarning(" -- b0: (%f,%f)", v
.x
, v
.y
);
2306 v
= b1
.unpack3f() - translation
;
2307 nlwarning(" -- b1: (%f,%f)", v
.x
, v
.y
);