World Path 2D.cpp 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848
  1. /******************************************************************************/
  2. #include "stdafx.h"
  3. namespace EE{
  4. namespace Game{
  5. /******************************************************************************/
  6. static void SetBasePathNodes(Area &area)
  7. {
  8. if(Area::Data *data=area.data())
  9. {
  10. if(!data->path2D())data->_path_node_offset=-1;else
  11. {
  12. AreaPath2D &path=*data->path2D();
  13. data->_path_node_offset=World._path_node.elms();
  14. if (path._changed)path.group();
  15. FREP(path._groups )
  16. {
  17. PathNode &pn=World._path_node.New();
  18. pn.node_index=data->_path_node_offset+i;
  19. pn.type = PN_AREA;
  20. pn.nghb_num= 0;
  21. pn.nghb_ofs= 0;
  22. pn.parent =-1; // no parent
  23. pn.sibling = data->_path_node_offset+i; // self
  24. pn.area.xy =area.xz();
  25. pn.area.index=i;
  26. }
  27. }
  28. }
  29. }
  30. static VecI2 Offsets[]=
  31. {
  32. VecI2(-1, 1),
  33. VecI2( 0, 1),
  34. VecI2( 1, 1),
  35. VecI2(-1, 0),
  36. //VecI2( 0, 0),
  37. VecI2( 1, 0),
  38. VecI2(-1,-1),
  39. VecI2( 0,-1),
  40. VecI2( 1,-1),
  41. };
  42. struct SetNeighborsHelper
  43. {
  44. PathNodeNeighbor neighbor [256][256]; // [group][neighbor]
  45. Int neighbors[256] ; // [group]
  46. Area::Data *data, *neighbor_data, *data_array[3][3]; // [y][x] orientation
  47. void addNeighbor(Int group, Int neighbor_index, Int cost)
  48. {
  49. // check if it's already written
  50. REP(neighbors[group]) // iterate through all neighbors of a node
  51. {
  52. if(neighbor[group][i].index==neighbor_index) // if i-th neighbor is 'neighbor_index'
  53. {
  54. MIN(neighbor[group][i].cost, cost); // decrease the travel cost
  55. return; // neighbor already exists so return
  56. }
  57. }
  58. // add new neighbor
  59. neighbor[group][neighbors[group]++].set(neighbor_index, cost);
  60. }
  61. void testLeft(Int y)
  62. {
  63. Byte group =data->path2D()->_map.pixB(0, y);
  64. if( group!=0xFF)
  65. {
  66. Byte group_b = data->path2D()->_map.pixB( 0, y-1),
  67. group_f = data->path2D()->_map.pixB( 0, y+1),
  68. neighbor_group_lb=neighbor_data->path2D()->_map.pixB(World.settings().path2DRes()-1, y-1),
  69. neighbor_group_l =neighbor_data->path2D()->_map.pixB(World.settings().path2DRes()-1, y ),
  70. neighbor_group_lf=neighbor_data->path2D()->_map.pixB(World.settings().path2DRes()-1, y+1);
  71. if(neighbor_group_l !=0xFF )addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_l , 5);
  72. if(neighbor_group_lb!=0xFF && (neighbor_group_l!=0xFF || group_b!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_lb, 7);
  73. if(neighbor_group_lf!=0xFF && (neighbor_group_l!=0xFF || group_f!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_lf, 7);
  74. }
  75. }
  76. void testRight(Int y)
  77. {
  78. Byte group =data->path2D()->_map.pixB(World.settings().path2DRes()-1, y);
  79. if( group!=0xFF)
  80. {
  81. Byte group_b = data->path2D()->_map.pixB(World.settings().path2DRes()-1, y-1),
  82. group_f = data->path2D()->_map.pixB(World.settings().path2DRes()-1, y+1),
  83. neighbor_group_rb=neighbor_data->path2D()->_map.pixB( 0, y-1),
  84. neighbor_group_r =neighbor_data->path2D()->_map.pixB( 0, y ),
  85. neighbor_group_rf=neighbor_data->path2D()->_map.pixB( 0, y+1);
  86. if(neighbor_group_r !=0xFF )addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_r , 5);
  87. if(neighbor_group_rb!=0xFF && (neighbor_group_r!=0xFF || group_b!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_rb, 7);
  88. if(neighbor_group_rf!=0xFF && (neighbor_group_r!=0xFF || group_f!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_rf, 7);
  89. }
  90. }
  91. void testBack(Int x)
  92. {
  93. Byte group =data->path2D()->_map.pixB(x, 0);
  94. if( group!=0xFF)
  95. {
  96. Byte group_l = data->path2D()->_map.pixB(x-1, 0),
  97. group_r = data->path2D()->_map.pixB(x+1, 0),
  98. neighbor_group_bl=neighbor_data->path2D()->_map.pixB(x-1, World.settings().path2DRes()-1),
  99. neighbor_group_b =neighbor_data->path2D()->_map.pixB(x , World.settings().path2DRes()-1),
  100. neighbor_group_br=neighbor_data->path2D()->_map.pixB(x+1, World.settings().path2DRes()-1);
  101. if(neighbor_group_b !=0xFF )addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_b , 5);
  102. if(neighbor_group_bl!=0xFF && (neighbor_group_b!=0xFF || group_l!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_bl, 7);
  103. if(neighbor_group_br!=0xFF && (neighbor_group_b!=0xFF || group_r!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_br, 7);
  104. }
  105. }
  106. void testForward(Int x)
  107. {
  108. Byte group =data->path2D()->_map.pixB(x, World.settings().path2DRes()-1);
  109. if( group!=0xFF)
  110. {
  111. Byte group_l = data->path2D()->_map.pixB(x-1, World.settings().path2DRes()-1),
  112. group_r = data->path2D()->_map.pixB(x+1, World.settings().path2DRes()-1),
  113. neighbor_group_fl=neighbor_data->path2D()->_map.pixB(x-1, 0),
  114. neighbor_group_f =neighbor_data->path2D()->_map.pixB(x , 0),
  115. neighbor_group_fr=neighbor_data->path2D()->_map.pixB(x+1, 0);
  116. if(neighbor_group_f !=0xFF )addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_f , 5);
  117. if(neighbor_group_fl!=0xFF && (neighbor_group_f!=0xFF || group_l!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_fl, 7);
  118. if(neighbor_group_fr!=0xFF && (neighbor_group_f!=0xFF || group_r!=0xFF))addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group_fr, 7);
  119. }
  120. }
  121. void testCorner(Int x, Int y)
  122. {
  123. Byte group =data->path2D()->_map.pixB(x, y);
  124. if( group!=0xFF)
  125. {
  126. REPA(Offsets)
  127. {
  128. Int sx=x+Offsets[i].x, ax=1,
  129. sy=y+Offsets[i].y, ay=1;
  130. if( sx<0){ax=0; sx+=World.settings().path2DRes();}else if(sx>=World.settings().path2DRes()){ax=2; sx-=World.settings().path2DRes();}
  131. if( sy<0){ay=0; sy+=World.settings().path2DRes();}else if(sy>=World.settings().path2DRes()){ay=2; sy-=World.settings().path2DRes();}
  132. if(ax!=1 || ay!=1) // test only external areas
  133. if(neighbor_data=data_array[ay][ax])
  134. {
  135. Byte neighbor_group =neighbor_data->path2D()->_map.pixB(sx, sy);
  136. if( neighbor_group!=0xFF)
  137. {
  138. Byte cost=5;
  139. if(Offsets[i].x && Offsets[i].y) // if we're going diagonally, then we need to check horizontal/vertical neighbors
  140. {
  141. Bool walkable_h=(data_array[1][ax] && data_array[1][ax]->path2D()->_map.pixB(sx,y)!=0xFF),
  142. walkable_v=(data_array[ay][1] && data_array[ay][1]->path2D()->_map.pixB(x,sy)!=0xFF);
  143. if( !walkable_h && !walkable_v)continue;
  144. cost=7;
  145. }
  146. addNeighbor(group, neighbor_data->_path_node_offset+neighbor_group, cost);
  147. }
  148. }
  149. }
  150. }
  151. }
  152. INLINE Area* getAreaActive(C VecI2 &xy) {return World.areaActive(xy) ;}
  153. INLINE Area* getArea (C VecI2 &xy) {return World._grid.get (xy).data();}
  154. SetNeighborsHelper(Area &area)
  155. {
  156. data=area.data(); REP(data->path2D()->_groups)neighbors[i]=0;
  157. #if 1 // faster but searches only through active areas
  158. Area *l =getAreaActive(area.xz()+VecI2(-1, 0)),
  159. *r =getAreaActive(area.xz()+VecI2( 1, 0)),
  160. *b =getAreaActive(area.xz()+VecI2( 0,-1)),
  161. *f =getAreaActive(area.xz()+VecI2( 0, 1)),
  162. *lb=getAreaActive(area.xz()+VecI2(-1,-1)),
  163. *lf=getAreaActive(area.xz()+VecI2(-1, 1)),
  164. *rb=getAreaActive(area.xz()+VecI2( 1,-1)),
  165. *rf=getAreaActive(area.xz()+VecI2( 1, 1));
  166. data_array[0][0]=((lb && lb->data() && lb->data()->path2D()) ? lb->data() : null);
  167. data_array[1][0]=((l && l ->data() && l ->data()->path2D()) ? l ->data() : null);
  168. data_array[2][0]=((lf && lf->data() && lf->data()->path2D()) ? lf->data() : null);
  169. data_array[0][1]=(( b && b->data() && b->data()->path2D()) ? b->data() : null);
  170. data_array[1][1]= data ;
  171. data_array[2][1]=(( f && f->data() && f->data()->path2D()) ? f->data() : null);
  172. data_array[0][2]=((rb && rb->data() && rb->data()->path2D()) ? rb->data() : null);
  173. data_array[1][2]=((r && r ->data() && r ->data()->path2D()) ? r ->data() : null);
  174. data_array[2][2]=((rf && rf->data() && rf->data()->path2D()) ? rf->data() : null);
  175. #else
  176. Area *l =getArea(area.xz()+VecI2(-1, 0)),
  177. *r =getArea(area.xz()+VecI2( 1, 0)),
  178. *b =getArea(area.xz()+VecI2( 0,-1)),
  179. *f =getArea(area.xz()+VecI2( 0, 1)),
  180. *lb=getArea(area.xz()+VecI2(-1,-1)),
  181. *lf=getArea(area.xz()+VecI2(-1, 1)),
  182. *rb=getArea(area.xz()+VecI2( 1,-1)),
  183. *rf=getArea(area.xz()+VecI2( 1, 1));
  184. data_array[0][0]=((lb && lb->_state==AREA_ACTIVE && lb->data() && lb->data()->path2D()) ? lb->data() : null);
  185. data_array[1][0]=((l && l ->_state==AREA_ACTIVE && l ->data() && l ->data()->path2D()) ? l ->data() : null);
  186. data_array[2][0]=((lf && lf->_state==AREA_ACTIVE && lf->data() && lf->data()->path2D()) ? lf->data() : null);
  187. data_array[0][1]=(( b && b->_state==AREA_ACTIVE && b->data() && b->data()->path2D()) ? b->data() : null);
  188. data_array[1][1]= data ;
  189. data_array[2][1]=(( f && f->_state==AREA_ACTIVE && f->data() && f->data()->path2D()) ? f->data() : null);
  190. data_array[0][2]=((rb && rb->_state==AREA_ACTIVE && rb->data() && rb->data()->path2D()) ? rb->data() : null);
  191. data_array[1][2]=((r && r ->_state==AREA_ACTIVE && r ->data() && r ->data()->path2D()) ? r ->data() : null);
  192. data_array[2][2]=((rf && rf->_state==AREA_ACTIVE && rf->data() && rf->data()->path2D()) ? rf->data() : null);
  193. #endif
  194. }
  195. };
  196. static void SetNeighbors(Area &area)
  197. {
  198. if(Area::Data *data=area.data())if(data->path2D())
  199. {
  200. AreaPath2D &path=*data->path2D();
  201. SetNeighborsHelper snh(area);
  202. // first add external neighbors because they require more testing
  203. if(snh.neighbor_data=snh.data_array[1][0])for(Int i=1; i<World.settings().path2DRes()-1; i++)snh.testLeft (i);
  204. if(snh.neighbor_data=snh.data_array[1][2])for(Int i=1; i<World.settings().path2DRes()-1; i++)snh.testRight (i);
  205. if(snh.neighbor_data=snh.data_array[0][1])for(Int i=1; i<World.settings().path2DRes()-1; i++)snh.testBack (i);
  206. if(snh.neighbor_data=snh.data_array[2][1])for(Int i=1; i<World.settings().path2DRes()-1; i++)snh.testForward(i);
  207. // add neighbors in corners
  208. snh.testCorner( 0, 0);
  209. snh.testCorner(World.settings().path2DRes()-1, 0);
  210. snh.testCorner( 0, World.settings().path2DRes()-1);
  211. snh.testCorner(World.settings().path2DRes()-1, World.settings().path2DRes()-1);
  212. // add local neighbors
  213. REPA(path._neighbor)
  214. {
  215. AreaPath2D::Neighbor &neighbor=path._neighbor[i];
  216. snh.addNeighbor(neighbor.a, data->_path_node_offset+neighbor.b, neighbor.cost);
  217. snh.addNeighbor(neighbor.b, data->_path_node_offset+neighbor.a, neighbor.cost);
  218. }
  219. // add to global list of neighbors
  220. REPD(g, path._groups)
  221. {
  222. PathNode &pn =World._path_node[data->_path_node_offset+g];
  223. pn.nghb_ofs=World._path_neighbor.elms();
  224. REPD(n, pn.nghb_num=snh.neighbors[g])World._path_neighbor.New()=snh.neighbor[g][n];
  225. }
  226. }
  227. }
  228. static Int PathNodeSiblings(Int i)
  229. {
  230. for(Int cur=i, num=0; ; num++)
  231. {
  232. cur =World._path_node[cur].sibling;
  233. if(cur==i)return num;
  234. }
  235. }
  236. void WorldManager::path2DBuild()
  237. {
  238. // clear path nodes and neighbors
  239. _path_node .clear();
  240. _path_neighbor.clear();
  241. // set base path nodes
  242. REPA(_area_active)SetBasePathNodes(*_area_active[i]);
  243. // set neighbors
  244. REPA(_area_active)SetNeighbors(*_area_active[i]);
  245. Memc<UInt > temp;
  246. Memc<PathNodeNeighbor> temp_neighbor;
  247. // join
  248. for(Int start=0, end; ; start=end)
  249. {
  250. // set parents
  251. end=_path_node.elms();
  252. if(start==end)break;
  253. for(Int i=start; i<end; i++) // all newly added nodes
  254. {
  255. PathNode &pn=_path_node[i];
  256. if(pn.nghb_num && pn.parent<0) // has neighbors and no parent (no one has taken him yet)
  257. {
  258. // check if there's at least one neighbor without parent
  259. REPD(n, pn.nghb_num)if(_path_node[_path_neighbor[pn.nghb_ofs+n].index].parent<0)goto has_at_least_one_parentless_neighbor;
  260. temp.New()=i; // add to unassigned
  261. continue; // all neighbors are taken, so we need to test another node
  262. has_at_least_one_parentless_neighbor:; // we've found at least one neighbor
  263. Int parent_index=_path_node.addNum(1); // create a new parent
  264. PathNode &parent =_path_node[parent_index];
  265. PathNode &pn =_path_node[ i]; // !! after adding element to container old 'pn' reference could point in the wrong place !!
  266. parent.type = PN_NODE;
  267. parent.nghb_num= 0;
  268. parent.nghb_ofs= 0;
  269. parent.parent =-1;
  270. parent.sibling = parent_index; // self
  271. parent.node.child=i;
  272. Int cur=i;
  273. REPD(n, pn.nghb_num) // all neighbors
  274. {
  275. Int nghb_index=_path_neighbor[pn.nghb_ofs+n].index; // neighbor index
  276. PathNode &nghb =_path_node [ nghb_index] ; // neighbor node
  277. if(nghb.parent<0) // if parentless
  278. {
  279. nghb.parent =parent_index; // set parent
  280. nghb.sibling=cur; // set sibling
  281. cur =nghb_index; // new sibling index
  282. }
  283. }
  284. pn.parent =parent_index; // set parent
  285. pn.sibling=cur ; // set current path node sibling to last visited
  286. }
  287. }
  288. // assign those which don't have a parent, to the parent of neighbor with least amount of children
  289. REPA(temp)
  290. {
  291. Int unassigned_index = temp[i],
  292. min_siblings_num = 0,
  293. min_siblings_index=-1;
  294. PathNode &pn=_path_node[unassigned_index];
  295. if(pn.parent<0) // normally temp's should contain nodes with no parent, however there can be a case (in bad algorithm of assigning neighbors) when node A has B written as its neighbor, however B doesn't have A written as its neighbor, then despite the node could have been added to temp, the second node could have assigned him to his parent, that's why make sure that the node doesn't have a parent
  296. {
  297. REPD(n, pn.nghb_num) // all neighbors
  298. {
  299. Int nghb_index=_path_neighbor[pn.nghb_ofs+n].index;
  300. if(_path_node[nghb_index].parent>=0) // if the neighbor actually has a parent
  301. {
  302. Int siblings=PathNodeSiblings(nghb_index);
  303. if(min_siblings_index<0 || siblings<min_siblings_num){min_siblings_index=nghb_index; min_siblings_num=siblings;}
  304. }
  305. }
  306. if(min_siblings_index>=0) // we've found a neighbor with least amount of siblings
  307. {
  308. PathNode &nghb=_path_node[min_siblings_index]; // neighbor node
  309. pn .parent =nghb.parent ; // set the same parent
  310. pn .sibling=nghb.sibling ; // new points on the same which old has pointed to
  311. nghb.sibling=unassigned_index; // old points on the new one
  312. }
  313. }
  314. }
  315. temp.clear();
  316. // set neighbors for newly created parents
  317. for(Int i=end; i<_path_node.elms(); i++) // for each parent
  318. {
  319. PathNode &pn=_path_node[i];
  320. if(pn.type==PN_NODE && pn.node.child>=0) // if it has children
  321. {
  322. // search for parents of children neighbors
  323. for(Int cur_child=pn.node.child; ; ) // check children
  324. {
  325. PathNode &pn_child=_path_node[cur_child];
  326. REPD(n, pn_child.nghb_num) // for each neighbor of a child
  327. {
  328. PathNodeNeighbor &nghb=_path_neighbor[pn_child.nghb_ofs+n];
  329. Int nghb_parent =_path_node[nghb.index].parent; // check neighbors parent
  330. if( nghb_parent>=0 && nghb_parent!=i) // if parent exists and it's different than currently processed
  331. {
  332. REPA(temp_neighbor) // check if parent has already been added as a neighbor
  333. {
  334. PathNodeNeighbor &tn=temp_neighbor[i];
  335. if(tn.index==nghb_parent){MIN(tn.cost, nghb.cost); goto exists;}
  336. }
  337. temp_neighbor.New().set(nghb_parent, nghb.cost);
  338. exists:;
  339. }
  340. }
  341. cur_child= pn_child.sibling; // check next sibling
  342. if(cur_child==pn.node.child)break; // we've reached the beggining (we've checked all children)
  343. }
  344. // add neighbors
  345. pn.nghb_ofs=_path_neighbor.elms(); // set neighbor offset
  346. pn.nghb_num= temp_neighbor.elms(); // set neighbor count
  347. REPA(temp_neighbor)_path_neighbor.New()=temp_neighbor[i]; // set neighbors
  348. temp_neighbor.clear(); // clear the temp
  349. }
  350. }
  351. }
  352. }
  353. /******************************************************************************/
  354. AreaPath2D* WorldManager::path2DGet(C VecI2 &xz)
  355. {
  356. if(Area *area=areaLoaded(xz))if(area->loaded() && area->data())return area->data()->path2D();
  357. return null;
  358. }
  359. /******************************************************************************/
  360. Bool WorldManager::path2DWalkable(C Vec &pos)
  361. {
  362. VecI2 xz=worldToArea(pos);
  363. if(AreaPath2D *path=path2DGet(xz))
  364. {
  365. Vec2 pxy=(pos.xz()/areaSize()-Vec2(xz))*settings().path2DRes();
  366. return path->walkable(Mid(Trunc(pxy.x), 0, path->_map.w()-1),
  367. Mid(Trunc(pxy.y), 0, path->_map.h()-1));
  368. }
  369. return false;
  370. }
  371. /******************************************************************************/
  372. Int WorldManager::pathGetNode(C Vec &pos, VecI2 &path_xy)
  373. {
  374. VecI2 xz=worldToArea(pos);
  375. if(Cell<Area> *g=_grid.find(xz))if(g->data()->loaded())if(Area::Data *data=g->data()->data())if(AreaPath2D *path=data->path2D())
  376. {
  377. Vec2 pxy=(pos.xz()/areaSize()-Vec2(xz))*settings().path2DRes();
  378. path_xy.set(Mid(Trunc(pxy.x), 0, path->_map.w()-1),
  379. Mid(Trunc(pxy.y), 0, path->_map.h()-1));
  380. Byte index=path->_map.pixB(path_xy);
  381. if( index<path->_groups) // this already handles !=0xFF (which is being solid)
  382. return data->_path_node_offset+index;
  383. }
  384. return -1;
  385. }
  386. /******************************************************************************
  387. Path Graph:
  388. Starting from top, searching downwards
  389. F.top -> T.top top
  390. F.top-1 -> .. -> T.top-1 .
  391. .. .. .
  392. F.1 -> .. -> .. -> .. -> .. -> T.1 .
  393. F.0 -> .. -> .. -> .. -> .. -> .. -> .. -> T.0 0
  394. /******************************************************************************/
  395. struct TempNode
  396. {
  397. Int /*path_node, */path_node_last_visited;
  398. UInt length;
  399. void set(Int path_node) {/*T.path_node=path_node; */path_node_last_visited=-1; length=0xFFFFFFFF;}
  400. };
  401. static void PrepareTempNodes(WorldManager &world, Memc<TempNode> &temp_node, Int parent)
  402. {
  403. Int child=world._path_node[parent].node.child;
  404. for(Int cur=child; ; )
  405. {
  406. Int temp_index=temp_node.addNum(1);
  407. world._path_node[cur].temp=temp_index; // link PathNode with TempNode
  408. temp_node[temp_index].set(cur); // setup TempNode
  409. cur=world._path_node[cur].sibling; // take sibling
  410. if(cur==child)break; // we've reached the start
  411. }
  412. }
  413. Bool WorldManager::pathFindFast(Int node_from, Int node_to, Memc<UInt> &path)
  414. {
  415. path.clear();
  416. if(InRange(node_from, _path_node)
  417. && InRange(node_to , _path_node))
  418. {
  419. if(node_from==node_to)return true; // the same nodes
  420. Memc<UInt> from_start, to_end; // stack of first and last node levels
  421. for(Int from_cur=node_from, to_cur=node_to; ; )
  422. {
  423. Int from_parent=_path_node[from_cur].parent,
  424. to_parent=_path_node[to_cur ].parent;
  425. if(from_parent<0 || to_parent<0)break; // no parents
  426. // add to level stack
  427. from_start.add(from_cur);
  428. to_end .add( to_cur);
  429. if(from_parent==to_parent) // found the same parent
  430. {
  431. Memc<TempNode> temp_node;
  432. Memc<UInt > nodes[2] ;
  433. Memc<UInt > active ;
  434. Bool cur= 0,
  435. top=!cur;
  436. for(;;)
  437. {
  438. // remove from the stack the highest elements
  439. from_cur=from_start.pop();
  440. to_cur= to_end .pop();
  441. // go from 'from_cur' to 'nodes[top]' to 'to_cur' writing in 'nodes[cur]' all neighbors passed by (in order) (skipping 'from_cur' and 'to_cur')
  442. {
  443. Bool found;
  444. UInt found_length;
  445. Int found_index,
  446. found_last_visited,
  447. cur_node=from_cur;
  448. // go through 'nodes[top]' (these are following parents of 'cur_node' neighbors leading to 'to_cur', following parents are connected with each other)
  449. FREPD(p, nodes[top].elms()+1) // +1 means guaranteed walk to 'to_cur' parent
  450. {
  451. Int cur_parent=_path_node[cur_node].parent,
  452. new_parent=((p<nodes[top].elms()) ? nodes[top][p] : _path_node[to_cur].parent);
  453. // go from 'cur_node' to nearest child of 'new_parent' parent, we can walk only on 'cur_parent'
  454. if(cur_parent!=new_parent) // make sure that we're not already in the target parent
  455. {
  456. // prepare 'temp_node' on which we'll be walking (only from 'cur_parent')
  457. PrepareTempNodes(T, temp_node, cur_parent);
  458. // set start
  459. temp_node[_path_node[cur_node].temp].length=0;
  460. active.add(cur_node);
  461. // start searching
  462. for(found=false; ; )
  463. {
  464. REPAD(a, active) // order is important
  465. {
  466. cur_node=active[a];
  467. PathNode &pn =_path_node[cur_node];
  468. UInt cur_length= temp_node[pn .temp].length+1;
  469. REPD(n, pn.nghb_num) // check all neighbors
  470. {
  471. PathNodeNeighbor &nghb_info =_path_neighbor[pn.nghb_ofs+n];
  472. Int nghb_index=nghb_info.index;
  473. PathNode &nghb =_path_node[nghb_index];
  474. UInt new_length=cur_length+nghb_info.cost;
  475. if(nghb.parent==cur_parent) // it can be walked
  476. {
  477. if(new_length<temp_node[nghb.temp].length) // we've reached faster than using other way
  478. {
  479. temp_node[nghb.temp].length =new_length;
  480. temp_node[nghb.temp].path_node_last_visited=cur_node;
  481. active.include(nghb_index);
  482. }
  483. }else
  484. if(nghb.parent==new_parent) // target parent
  485. {
  486. if(nghb_index==to_cur)new_length--; // if we've encountered the target then bonus the length
  487. if(!found || new_length<found_length)
  488. {
  489. found =true;
  490. found_length=new_length;
  491. found_index =nghb_index;
  492. found_last_visited=cur_node;
  493. }
  494. }
  495. }
  496. active.remove(a);
  497. }
  498. if(found)
  499. {
  500. // iterate all visited nodes saving them (from end to start), use container 'active'
  501. // don't write where we've started, but write where we've ended up (so target without the first one)
  502. active.clear().add(found_index);
  503. for(;;)
  504. {
  505. Int last_visited=temp_node[_path_node[found_last_visited].temp].path_node_last_visited;
  506. if( last_visited<0)break; // 'found_last_visited' was first because no one visited him, and since we don't add the first so let's break
  507. active.add(found_last_visited);
  508. found_last_visited=last_visited;
  509. }
  510. // add 'active' in the right order to 'nodes[cur]'
  511. REPA(active)nodes[cur].add(active[i]);
  512. cur_node=found_index; // set current as last found
  513. break;
  514. }
  515. if(!active.elms())return false; // shouldn't happen
  516. }
  517. active .clear();
  518. temp_node.clear();
  519. }
  520. }
  521. // go to 'to_cur'
  522. if(cur_node==to_cur) // we're already there
  523. {
  524. if(nodes[cur].elms() && nodes[cur].last()==to_cur)nodes[cur].removeLast(); // if one node was added too much
  525. }else
  526. {
  527. // we're already at 'to_parent' parent, we're searching path from 'cur_node' to 'to_cur' without writing the first and last one on the road (without 'cur_node' and 'to_cur')
  528. // prepare 'temp_node' on which we'll be walking (only from 'to_parent')
  529. PrepareTempNodes(T, temp_node, to_parent);
  530. // set start
  531. temp_node[_path_node[cur_node].temp].length=0;
  532. active.add(cur_node);
  533. // start searching
  534. for(found=false; ; )
  535. {
  536. REPAD(a, active) // order is important
  537. {
  538. cur_node=active[a];
  539. PathNode &pn =_path_node[cur_node];
  540. UInt cur_length= temp_node[pn .temp].length+1;
  541. REPD(n, pn.nghb_num) // check all neighbors
  542. {
  543. PathNodeNeighbor &nghb_info =_path_neighbor[pn.nghb_ofs+n];
  544. Int nghb_index=nghb_info.index;
  545. PathNode &nghb =_path_node[nghb_index];
  546. UInt new_length=cur_length+nghb_info.cost;
  547. if(nghb.parent==to_parent // consider only nodes in the final parent 'to_parent'
  548. && new_length<temp_node[nghb.temp].length) // we've reached faster than using a different way
  549. {
  550. temp_node[nghb.temp].length =new_length;
  551. temp_node[nghb.temp].path_node_last_visited=cur_node;
  552. if(nghb_index==to_cur) // found, this is the last element
  553. {
  554. found=true;
  555. found_last_visited=cur_node;
  556. }else
  557. {
  558. active.include(nghb_index);
  559. }
  560. }
  561. }
  562. active.remove(a);
  563. }
  564. if(found)
  565. {
  566. // iterate all visited nodes saving them (from end to start), use container 'active'
  567. // don't write where we've started and when we're finishing (skip last and first ones)
  568. active.clear();
  569. for(;;)
  570. {
  571. Int last_visited=temp_node[_path_node[found_last_visited].temp].path_node_last_visited;
  572. if( last_visited<0)break; // 'found_last_visited' was first because no one visited him, and since we don't add the first so let's break
  573. active.add(found_last_visited);
  574. found_last_visited=last_visited;
  575. }
  576. // add 'active' in the right order to 'nodes[cur]'
  577. REPA(active)nodes[cur].add(active[i]);
  578. break; // found last element on this level
  579. }
  580. if(!active.elms())return false; // shouldn't happen
  581. }
  582. active .clear();
  583. temp_node.clear();
  584. }
  585. }
  586. // finish
  587. if(!from_start.elms() || !to_end.elms())
  588. {
  589. // nodes[cur] is a path
  590. path.add(node_to ); // add target node
  591. REPA(nodes[cur])path.add(nodes[cur][i]); // add in reversed order
  592. return true;
  593. }
  594. Swap(top, cur);
  595. nodes[cur].clear();
  596. from_parent=from_cur;
  597. to_parent= to_cur;
  598. }
  599. #if DEBUG
  600. //pathDraw(from_cur, GREEN);
  601. //pathDraw( to_cur, RED );
  602. #endif
  603. break;
  604. }
  605. from_cur=from_parent;
  606. to_cur= to_parent;
  607. }
  608. }
  609. return false;
  610. }
  611. /******************************************************************************/
  612. Bool WorldManager::pathFind(Int node_from, Int node_to, Memc<UInt> &path)
  613. {
  614. path.clear();
  615. if(InRange(node_from, _path_node)
  616. && InRange(node_to , _path_node))
  617. {
  618. if(node_from==node_to)return true; // the same nodes
  619. // check if it's possible to find a path (they have mutual ancestors)
  620. for(Int from_parent=node_from, to_parent=node_to; ; )
  621. {
  622. from_parent=_path_node[from_parent].parent;
  623. to_parent=_path_node[ to_parent].parent;
  624. if(from_parent<0 || to_parent<0)return false; // no parents
  625. if(from_parent == to_parent )break ; // found the same parent
  626. }
  627. // update iterations (reset nodes if needed)
  628. if(++_path_iteration==0) // we've reset the counter (got back to zero again)
  629. {
  630. FREPA(_path_node) // reset nodes, from the start to skip parents
  631. {
  632. PathNode &pn=_path_node[i]; if(pn.type!=PN_AREA)break; // we've encountered a parent so break
  633. pn.iteration=0; // reset iteration
  634. }
  635. _path_iteration=1;
  636. }
  637. Memc<PathNode*> active;
  638. // setup first step
  639. _path_node[node_from].iteration=_path_iteration;
  640. _path_node[node_from].length =0;
  641. _path_node[node_from].src =null;
  642. active.clear().add(&_path_node[node_from]);
  643. // start searching
  644. UInt found_length;
  645. PathNode *found=null;
  646. for(Int step=0; ; step++)
  647. {
  648. REPA(active) // order is important
  649. {
  650. PathNode *p=active[i]; // for each walker
  651. UInt cur_length=p->length; // total length travelled by the walker
  652. REPD(n, p->nghb_num) // try going in each direction
  653. {
  654. PathNodeNeighbor &pnn=_path_neighbor[p->nghb_ofs+n];
  655. PathNode &to =_path_node [pnn.index]; // target node
  656. UInt new_length=cur_length+pnn.cost;
  657. // zero if not yet used
  658. if(to.iteration!=_path_iteration)
  659. {
  660. to.iteration =_path_iteration;
  661. to.added_in_step=-1;
  662. to.length =UINT_MAX;
  663. }
  664. if(new_length<to.length)
  665. {
  666. if(pnn.index==node_to)
  667. {
  668. to.length=new_length;
  669. to.src =p;
  670. if(!found || new_length<found_length)
  671. {
  672. found =&to;
  673. found_length=new_length;
  674. }
  675. }else
  676. {
  677. to.length=new_length;
  678. to.src =p;
  679. if(to.added_in_step!=step) // to not add multiple times in the same step
  680. {
  681. to.added_in_step=step;
  682. active.add(&to);
  683. }
  684. }
  685. }
  686. }
  687. active.remove(i);
  688. }
  689. if(found) // found path
  690. {
  691. // build path
  692. for(;;)
  693. {
  694. PathNode *src=found->src;
  695. if( !src)break;
  696. path.add(found->node_index);
  697. found=src;
  698. }
  699. return true;
  700. }
  701. if(!active.elms())return false;
  702. }
  703. }
  704. return false;
  705. }
  706. /******************************************************************************/
  707. void WorldManager::pathDrawArea(Area &area, Byte index, C Color &color)
  708. {
  709. if(area.loaded() && area.data())if(AreaPath2D *path=area.data()->path2D())
  710. {
  711. Image &height=area.data()->height;
  712. Flt scale =Flt(height.w()-1)/settings().path2DRes();
  713. VI.color(color);
  714. SetOneMatrix(Matrix(Vec(areaSize()/settings().path2DRes(), 1, areaSize()/settings().path2DRes()), (area.xz()*areaSize()).x0y()));
  715. REPD(y, path->_map.h())
  716. REPD(x, path->_map.w())if(path->_map.pixB(x, y)==index)
  717. {
  718. Quad q;
  719. q.p[0].set(x , height.pixelF( x *scale, (y+1)*scale), y+1);
  720. q.p[1].set(x+1, height.pixelF((x+1)*scale, (y+1)*scale), y+1);
  721. q.p[2].set(x+1, height.pixelF((x+1)*scale, y *scale), y );
  722. q.p[3].set(x , height.pixelF( x *scale, y *scale), y );
  723. VI.quad(q);
  724. }
  725. VI.end();
  726. }
  727. }
  728. void WorldManager::pathDraw(Int node, C Color &color)
  729. {
  730. if(InRange(node, _path_node))
  731. {
  732. PathNode &pn=_path_node[node];
  733. switch(pn.type)
  734. {
  735. case PN_NODE:
  736. {
  737. Int child=pn.node.child;
  738. for(Int c=child; c>=0; )
  739. {
  740. pathDraw(c, color);
  741. c= _path_node[c].sibling; // grab the next one
  742. if(c==child)break; // we've reached the start
  743. }
  744. }break;
  745. case PN_AREA:
  746. {
  747. if(Cell<Area> *cell=_grid.find(pn.area.xy))pathDrawArea(*cell->data(), pn.area.index, color);
  748. }break;
  749. }
  750. }
  751. }
  752. void WorldManager::pathDrawNghb(Int node, C Color &color)
  753. {
  754. if(InRange(node, _path_node))
  755. {
  756. PathNode &pn=_path_node[node];
  757. REP(pn.nghb_num)pathDraw(_path_neighbor[pn.nghb_ofs+i].index, color);
  758. }
  759. }
  760. void WorldManager::pathDrawBlock(C Color &color)
  761. {
  762. REPA(_area_active)pathDrawArea(*_area_active[i], 0xFF, color);
  763. }
  764. /******************************************************************************/
  765. }}
  766. /******************************************************************************/