Fix game:addSpawnShapesByZone
[ryzomcore.git] / nel / tools / pacs / build_rbank / surface_splitter.cpp
blob72e6eeb4d5f811abef7c8f784017e2d78deb2eaa
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 "surface_splitter.h"
19 using namespace std;
20 using namespace NLMISC;
21 using namespace NLPACS;
23 // -----------------------
26 // Constructor
27 CSurfaceSplitter::CSurfaceSplitter()
33 void CSurfaceSplitter::build(CLocalRetriever &lr)
35 nlinfo("--- Build SurfaceSplitter...");
36 nlinfo("------------------------------------------");
37 uint i;
39 initEdgeGrid();
41 _NumChains = 0;
42 _NumSurfaces = 0;
43 _NumTips = 0;
45 for (i=0; i<lr.getChains().size(); ++i)
46 buildChain(lr, i);
48 for (i=0; i<lr.getSurfaces().size(); ++i)
49 buildSurface(lr, i);
51 nlinfo("converted %d chains & %d surfaces", lr.getChains().size(), lr.getSurfaces().size());
52 _NumSurfaces = (uint)lr.getSurfaces().size();
53 _NumChains = (uint)lr.getChains().size();
55 //splitChains();
57 dump();
59 nlinfo("------------------------------------------");
63 void CSurfaceSplitter::buildChain(CLocalRetriever &lr, uint chain)
65 const NLPACS::CChain &pacsChain = lr.getChain(chain);
67 CSurfaceId left = pacsChain.getLeft() >= 0 ? CSurfaceId(0, (uint16)pacsChain.getLeft()) : CSurfaceId();
68 CSurfaceId right = pacsChain.getRight() >= 0 ? CSurfaceId(0, (uint16)pacsChain.getRight()) : CSurfaceId();
69 vector<CVector2s64> vertices;
71 uint i;
72 // walk through all subchains
73 for (i=0; i<pacsChain.getSubChains().size(); ++i)
75 uint ochain = pacsChain.getSubChain(i);
76 const NLPACS::COrderedChain &pacsOChain = lr.getOrderedChain(ochain);
78 sint j;
79 // walk through subchain, forward or backward
80 if (pacsOChain.isForward())
82 for (j=0; j<(sint)pacsOChain.getVertices().size()-1; ++j)
83 vertices.push_back(CVector2s64(pacsOChain[j]));
85 else
87 for (j=(sint)pacsOChain.getVertices().size()-1; j>0; --j)
88 vertices.push_back(CVector2s64(pacsOChain[j]));
91 // add final chain point
92 if (i == pacsChain.getSubChains().size()-1)
93 vertices.push_back(CVector2s64(pacsOChain[j]));
96 addChain(left,right, vertices);
100 void CSurfaceSplitter::buildSurface(CLocalRetriever &lr, uint surface)
102 const NLPACS::CRetrievableSurface &pacsSurface = lr.getSurface(surface);
103 CSurface newSurface;
105 newSurface.Id = CSurfaceId(0, surface);
107 uint i;
108 // walk through all loops
109 for (i=0; i<pacsSurface.getLoops().size(); ++i)
111 const NLPACS::CRetrievableSurface::TLoop &pacsLoop = pacsSurface.getLoop(i);
112 newSurface.Loops.push_back(CSurfaceSplitter::CLoop());
113 newSurface.Loops.back().Surface = newSurface.Id;
115 uint j;
116 // walk through loop
117 for (j=0; j<pacsLoop.size(); ++j)
119 uint chainIndex = pacsLoop[j];
120 uint chain = pacsSurface.getChain(chainIndex).Chain;
122 newSurface.Loops.back().Chains.push_back(CChainId(chain));
126 _Surfaces.insert(make_pair(newSurface.Id, newSurface));
132 void CSurfaceSplitter::initEdgeGrid()
134 _Edges.create(256, 2.0f);
139 void CSurfaceSplitter::splitChains()
141 nlinfo("Split chains...");
143 uint numInters = 0;
144 uint i;
146 for (i=0; i<_NumChains; ++i)
148 TChainMap::iterator it = _Chains.find(CChainId(i));
149 if (it != _Chains.end())
150 splitChain(it, numInters);
153 nlinfo("%d intersections found", numInters);
157 void CSurfaceSplitter::splitChain(TChainMap::iterator it, uint &numInters)
159 CChain &chain = (*it).second;
161 if (chain.DontSplit)
162 return;
164 uint edge;
165 // for each edge of the chain, test for other edges collision
166 for (edge=0; edge<chain.Vertices.size()-1; ++edge)
168 CVector p0 = chain.Vertices[edge].asVector();
169 CVector p1 = chain.Vertices[edge+1].asVector();
170 CVector pmin, pmax;
171 pmin.minof(p0, p1);
172 pmax.maxof(p0, p1);
174 _Edges.select(pmin, pmax);
176 CFixed64 closerDist(10.0);
177 bool collisionFound = false;
178 CEdgeId collidingEdge;
179 CVector2s64 collision;
181 TEdgeGrid::CIterator it;
182 for (it=_Edges.begin(); it!=_Edges.end(); ++it)
184 CEdgeId iedge = *it;
187 if (chain.Id == iedge.Chain && (edge == iedge.Edge || edge+1 == iedge.Edge || edge-1 == iedge.Edge))
188 continue;
190 CChain *ichain = getChain(iedge.Chain);
192 if (ichain == NULL)
194 nlwarning("Couldn't find referenced chain %d", iedge.Chain.Id);
195 continue;
198 if (ichain->DontSplit)
199 continue;
201 CVector2s64 inters;
202 CFixed64 ndist;
204 if (intersect(chain.Vertices[edge], chain.Vertices[edge+1], ichain->Vertices[iedge.Edge], ichain->Vertices[iedge.Edge+1], inters, ndist))
206 if (inters != chain.Vertices[edge+1] || edge != chain.Vertices.size()-2)
208 ++numInters;
209 nlinfo("Intersection: %d:%d[%.3f,%.3f-%.3f,%.3f]-%d:%d[%.3f,%.3f-%.3f,%.3f] : [%.3f,%.3f]", chain.Id.Id, edge, p0.x, p0.y, p1.x, p1.y, iedge.Chain.Id, iedge.Edge, ichain->Vertices[iedge.Edge].asVector().x, ichain->Vertices[iedge.Edge].asVector().y, ichain->Vertices[iedge.Edge+1].asVector().x, ichain->Vertices[iedge.Edge+1].asVector().y, inters.asVector().x, inters.asVector().y);
211 if (closerDist > ndist)
213 collisionFound = true;
214 collidingEdge = iedge;
215 collision = inters;
218 else
220 nlinfo("Intersection: %d:%d[%.3f,%.3f-%.3f,%.3f]-%d:%d[%.3f,%.3f-%.3f,%.3f] : [%.3f,%.3f] -- SKIPPED", chain.Id.Id, edge, p0.x, p0.y, p1.x, p1.y, iedge.Chain.Id, iedge.Edge, ichain->Vertices[iedge.Edge].asVector().x, ichain->Vertices[iedge.Edge].asVector().y, ichain->Vertices[iedge.Edge+1].asVector().x, ichain->Vertices[iedge.Edge+1].asVector().y, inters.asVector().x, inters.asVector().y);
225 // split chain
226 if (collisionFound)
228 if (chain.Id == collidingEdge.Chain)
230 // self colliding chain
232 // check order
233 //nlassert(edge >= 0); // always true for unsigned
234 nlassert(edge < collidingEdge.Edge);
235 nlassert(collidingEdge.Edge < chain.Vertices.size()-1);
237 // must split the chain in 3 parts
238 uint e;
239 vector<CVector2s64> begin;
240 vector<CVector2s64> middle;
241 vector<CVector2s64> end;
242 vector<CChainId> v;
243 CChainId beginId;
244 CChainId middleId;
245 CChainId endId;
247 for (e=0; e<=edge; ++e)
248 begin.push_back(chain.Vertices[e]);
250 begin.push_back(collision);
252 if (collision != chain.Vertices[e])
253 middle.push_back(collision);
255 for (; e<=collidingEdge.Edge; ++e)
256 middle.push_back(chain.Vertices[e]);
258 middle.push_back(collision);
260 if (collision != chain.Vertices[e])
261 end.push_back(collision);
263 for (; e<chain.Vertices.size(); ++e)
264 end.push_back(chain.Vertices[e]);
266 beginId = addChain(chain.Left, chain.Right, begin, true);
267 middleId = addChain(chain.Left, chain.Right, middle);
268 endId = addChain(chain.Left, chain.Right, end);
270 v.push_back(beginId);
271 v.push_back(middleId);
272 v.push_back(endId);
274 replaceChain(chain.Id, v);
276 else
278 //nlassert(edge >= 0); // always true for unsigned
279 nlassert(edge < chain.Vertices.size()-1);
281 // split the chain
282 uint e;
283 vector<CVector2s64> begin;
284 vector<CVector2s64> end;
285 vector<CChainId> v;
286 CChainId beginId;
287 CChainId endId;
289 // split the first chain
290 for (e=0; e<=edge; ++e)
291 begin.push_back(chain.Vertices[e]);
293 begin.push_back(collision);
295 if (collision != chain.Vertices[e])
296 end.push_back(collision);
298 for (; e<chain.Vertices.size(); ++e)
299 end.push_back(chain.Vertices[e]);
301 beginId = addChain(chain.Left, chain.Right, begin, true);
302 endId = addChain(chain.Left, chain.Right, end);
304 v.push_back(beginId);
305 v.push_back(endId);
307 replaceChain(chain.Id, v);
309 // reset for second chain
310 begin.clear();
311 end.clear();
312 v.clear();
314 // split the second chain
315 CChain *collide = getChain(collidingEdge.Chain);
317 for (e=0; e<=collidingEdge.Edge; ++e)
318 begin.push_back(collide->Vertices[e]);
320 begin.push_back(collision);
322 if (collision != collide->Vertices[e])
323 end.push_back(collision);
325 for (; e<collide->Vertices.size(); ++e)
326 end.push_back(collide->Vertices[e]);
328 beginId = addChain(collide->Left, collide->Right, begin);
329 endId = addChain(collide->Left, collide->Right, end);
331 v.push_back(beginId);
332 v.push_back(endId);
334 replaceChain(collide->Id, v);
337 return;
343 bool CSurfaceSplitter::intersect(const CVector2s64 &v0, const CVector2s64 &v1,
344 const CVector2s64 &c0, const CVector2s64 &c1,
345 CVector2s64 &intersect,
346 CFixed64 &ndist)
348 if (v0 == c0 || v0 == c1)
349 return false;
351 if (v1 == c0 || v1 == c1)
353 intersect = v1;
354 ndist = CFixed64(1.0);
355 return true;
358 CVector2s64 nnc(c0.y-c1.y, c1.x-c0.x),
359 nnv(v0.y-v1.y, v1.x-v0.x);
361 CFixed64 dv = (v1-v0)*nnc;
363 // vectors are colinears ?
364 if ((sint64)dv == 0)
365 return false;
367 CFixed64 nv = (c0-v0)*nnc;
369 if ((sint64)dv < 0)
370 dv=-dv, nv=-nv;
371 // intersection outside main edge ? (or at first point ?)
372 if ((sint64)nv<=0 || nv>dv)
373 return false;
375 CFixed64 dc = (c1-c0)*(c1-c0);
376 // second edge null ?
377 if ((sint64)dc == 0)
378 return false;
380 CFixed64 lv = nv/dv;
382 if ((sint64)lv == 0)
383 return false;
385 CFixed64 nc = (v0-c0 + (v1-v0)*lv)*(c1-c0);
386 // intersection outside colliding edge ?
387 if ((sint64)nc<0 || nc>dc)
388 return false;
390 // treat each singular case
391 if (nv == dv)
392 intersect = v1;
393 else if ((sint64)nc == 0)
394 intersect = c0;
395 else if (nc == dc)
396 intersect = c1;
397 else
398 // compute intersecting point
399 intersect = v0 + (v1-v0)*lv;
401 ndist = lv;
403 return true;
409 CSurfaceSplitter::CChainId CSurfaceSplitter::addChain(const CSurfaceId &left, const CSurfaceId &right, const vector<CVector2s64> &points, bool dontSplit)
411 pair<TChainMap::iterator, bool> res = _Chains.insert(make_pair(CChainId(_NumChains++), CChain()));
413 CChain &chain = (*(res.first)).second;
415 chain.Id = (*(res.first)).first;
416 chain.Left = left;
417 chain.Right = right;
419 uint i;
420 for (i=0; i<points.size()-1; ++i)
422 if (points[i] == points[i+1])
424 nlwarning("--- !! points are together !! ---");
425 nlstop;
429 chain.Vertices = points;
430 chain.DontSplit = dontSplit;
432 uint edge;
433 for (edge=0; edge<chain.Vertices.size()-1; ++edge)
435 CVector p0 = chain.Vertices[edge].asVector();
436 CVector p1 = chain.Vertices[edge+1].asVector();
438 p0.z = -100.0f;
439 p1.z = +100.0f;
441 CVector pmin, pmax;
442 pmin.minof(p0, p1);
443 pmax.maxof(p0, p1);
445 chain.Iterators.push_back(_Edges.insert(pmin, pmax, CEdgeId(chain.Id, edge)));
448 return chain.Id;
452 void CSurfaceSplitter::removeChain(CChainId chainId)
454 // get chain it
455 TChainMap::iterator it = _Chains.find(chainId);
457 if (it == _Chains.end())
458 return;
460 CChain &chain = (*it).second;
462 CSurface *surf;
464 if ((surf = getSurface(chain.Left)))
465 surf->removeChain(chainId);
467 if ((surf = getSurface(chain.Right)))
468 surf->removeChain(chainId);
472 void CSurfaceSplitter::replaceChain(CChainId chainId, const vector<CChainId> &chains)
474 // get chain it
475 TChainMap::iterator it = _Chains.find(chainId);
477 if ((it == _Chains.end()))
478 return;
480 CChain &chain = (*it).second;
482 CSurface *surf;
484 nlinfo("-- Replace --");
485 dumpChain(chainId);
486 nlinfo("-- By --");
487 uint c;
488 for (c=0; c<chains.size(); ++c)
489 dumpChain(chains[c]);
490 nlinfo("-- End Replace --");
492 if ((surf = getSurface(chain.Left)))
494 uint loop;
495 for (loop=0; loop<surf->Loops.size(); ++loop)
497 CLoop &ploop = surf->Loops[loop];
498 vector<CChainId>::iterator it;
499 for (it=ploop.Chains.begin(); it!=ploop.Chains.end(); ++it)
501 if (*it == chainId)
503 it = ploop.Chains.erase(it);
504 sint i;
505 for (i=(sint)chains.size()-1; i>=0; --i)
507 it = ploop.Chains.insert(it, chains[i]);
514 if ((surf = getSurface(chain.Right)))
516 uint loop;
517 for (loop=0; loop<surf->Loops.size(); ++loop)
519 CLoop &ploop = surf->Loops[loop];
520 vector<CChainId>::iterator it;
521 for (it=ploop.Chains.begin(); it!=ploop.Chains.end(); ++it)
523 if (*it == chainId)
525 it = ploop.Chains.erase(it);
526 uint i;
527 for (i=0; i<chains.size(); ++i)
529 it = ploop.Chains.insert(it, chains[i]);
536 uint i;
537 for (i=0; i<chain.Iterators.size(); ++i)
538 _Edges.erase(chain.Iterators[i]);
540 _Chains.erase(it);