ObjectsFindManager.cpp 29 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094
  1. //============================================================================================
  2. // Spirenkov Maxim, 2004, 2008
  3. //============================================================================================
  4. // ObjectFindManager (quad tree)
  5. //============================================================================================
  6. #include "ObjectsFindManager.h"
  7. #define ENABLE_NAN_CHECK
  8. //#define ENABLE_NAN_STOP
  9. //============================================================================================
  10. //Abb
  11. //============================================================================================
  12. __forceinline ObjectsFindManager::Abb::Abb()
  13. {
  14. }
  15. __forceinline ObjectsFindManager::Abb::Abb(const Abb & abb)
  16. {
  17. minX = abb.minX; maxX = abb.maxX;
  18. minZ = abb.minZ; maxZ = abb.maxZ;
  19. }
  20. __forceinline ObjectsFindManager::Abb::Abb(long _minX, long _maxX, long _minZ, long _maxZ)
  21. {
  22. minX = _minX; maxX = _maxX;
  23. minZ = _minZ; maxZ = _maxZ;
  24. }
  25. __forceinline bool ObjectsFindManager::Abb::IsInclude(const Abb & abb) const
  26. {
  27. if(minX <= abb.minX && maxX >= abb.maxX)
  28. {
  29. if(minZ <= abb.minZ && maxZ >= abb.maxZ)
  30. {
  31. return true;
  32. }
  33. }
  34. return false;
  35. }
  36. __forceinline bool ObjectsFindManager::Abb::IsIntersection(const Abb & abb) const
  37. {
  38. if(minX <= abb.maxX && maxX >= abb.minX)
  39. {
  40. if(minZ <= abb.maxZ && maxZ >= abb.minZ)
  41. {
  42. return true;
  43. }
  44. }
  45. return false;
  46. }
  47. __forceinline long ObjectsFindManager::Abb::MinSize() const
  48. {
  49. return coremin(maxX - minX, maxZ - minZ);
  50. }
  51. __forceinline bool ObjectsFindManager::Abb::Set(Vector min, Vector max, bool isChecker)
  52. {
  53. //Границы
  54. const float roundValue = 0.999999f;
  55. if(isChecker)
  56. {
  57. if(min.x > max.x)
  58. {
  59. Swap(min.x, max.x);
  60. }
  61. if(min.z > max.z)
  62. {
  63. Swap(min.z, max.z);
  64. }
  65. }
  66. min.x -= roundValue;
  67. min.z -= roundValue;
  68. max.x += roundValue;
  69. max.z += roundValue;
  70. //Проверяем на попадание ректа в рабочий диапазон
  71. const float range = 1000000.0f;
  72. bool inRange = true;
  73. if(!isChecker)
  74. {
  75. if(min.x < -range || min.x > range) inRange = false;
  76. if(min.z < -range || min.z > range) inRange = false;
  77. if(max.x < -range || max.x > range) inRange = false;
  78. if(max.z < -range || max.z > range) inRange = false;
  79. }else{
  80. const float clampValue = range*1.1f;
  81. min.x = Clampf(min.x, -clampValue, clampValue);
  82. min.z = Clampf(min.z, -clampValue, clampValue);
  83. max.x = Clampf(max.x, -clampValue, clampValue);
  84. max.z = Clampf(max.z, -clampValue, clampValue);
  85. }
  86. //Преобразуем результат к целым числам
  87. if(inRange)
  88. {
  89. minX = long(min.x);
  90. maxX = long(max.x);
  91. minZ = long(min.z);
  92. maxZ = long(max.z);
  93. /*
  94. #ifndef STOP_ASSERTS
  95. if(AssertInRange("ObjectsFindManager::Abb::Set", true))
  96. {
  97. api->Trace("Inc abb: min = %f, %f; max = %f, %f", min.x, min.z, max.x, max.z);
  98. }
  99. #endif
  100. */
  101. }
  102. return inRange;
  103. }
  104. #ifndef STOP_ASSERTS
  105. __forceinline bool ObjectsFindManager::Abb::AssertInRange(const char * prefix, bool noStop) const
  106. {
  107. const long range = 2000000;
  108. bool outOfRange = false;
  109. if(minX < -range || minX > range)
  110. {
  111. outOfRange = true;
  112. }
  113. if(minZ < -range || minZ > range)
  114. {
  115. outOfRange = true;
  116. }
  117. if(maxX < -range || maxX > range)
  118. {
  119. outOfRange = true;
  120. }
  121. if(maxZ < -range || maxZ > range)
  122. {
  123. outOfRange = true;
  124. }
  125. if(outOfRange)
  126. {
  127. LogOut(prefix);
  128. Assert(noStop);
  129. }
  130. return outOfRange;
  131. }
  132. #endif
  133. __forceinline void ObjectsFindManager::Abb::LogOut(const char * prefix) const
  134. {
  135. #ifndef STOP_DEBUG
  136. api->Trace("%s Abb: min(x: %i, z: %i) max(x: %i, z: %i)", prefix, minX, minZ, maxX, maxZ);
  137. #endif
  138. }
  139. //============================================================================================
  140. //TreeObject
  141. //============================================================================================
  142. ObjectsFindManager::TreeObject::TreeObject(MissionObject * _mo, ObjectsFindManager * _mng)
  143. {
  144. //Заполняем поля
  145. Assert(_mo);
  146. Assert(_mng);
  147. flags = f_invalidateAbb;
  148. node = null;
  149. mng = _mng;
  150. nextInNode = null;
  151. prevInNode = null;
  152. nextInList = null;
  153. prevInList = null;
  154. abb.minX = 0;
  155. abb.maxX = 0;
  156. abb.minZ = 0;
  157. abb.maxZ = 0;
  158. center = 0.0f;
  159. size = 0.0f;
  160. mo = _mo;
  161. userData = null;
  162. cppFile = null;
  163. cppLine = 0;
  164. pullCode = 0;
  165. tmp = 0;
  166. //Добавляемся в список неактивных
  167. MoveToInactiveList();
  168. }
  169. //Освободить ресурсы
  170. void ObjectsFindManager::TreeObject::Release()
  171. {
  172. //Исключаемся из всех возможных списков
  173. Assert(mng);
  174. RemoveFromNode();
  175. RemoveFromLists();
  176. //Чистим нужное
  177. flags = f_deleted;
  178. node = null;
  179. mo = null;
  180. userData = null;
  181. //Удаляем объект
  182. Delete(this);
  183. // api->Trace("Release object = %x", this);
  184. }
  185. //Изменить активность
  186. void ObjectsFindManager::TreeObject::Activate(bool isActive)
  187. {
  188. if(isActive)
  189. {
  190. //Если активны то ничего не делаем
  191. if(flags & f_active)
  192. {
  193. return;
  194. }
  195. //Пометим флажёк что хотим быть активными
  196. flags |= f_active;
  197. //Если бокс кривой то больше ничего не делаем
  198. if(flags & f_invalidateAbb)
  199. {
  200. return;
  201. }
  202. //Переходим в список обновления
  203. MoveToUpdateList();
  204. }else{
  205. if(!(flags & f_active))
  206. {
  207. return;
  208. }
  209. //Переходим в список неактивных
  210. RemoveFromNode();
  211. MoveToInactiveList();
  212. }
  213. }
  214. //Активен ли объект
  215. bool ObjectsFindManager::TreeObject::IsActivate()
  216. {
  217. return (flags & f_active) != 0;
  218. }
  219. //Получить указатель на объект миссии
  220. MissionObject & ObjectsFindManager::TreeObject::GetMissionObject()
  221. {
  222. Assert(mo);
  223. return *mo;
  224. }
  225. //Установить пользовательские данные
  226. void ObjectsFindManager::TreeObject::SetUserData(void * data)
  227. {
  228. userData = data;
  229. }
  230. //Получить пользовательские данные
  231. void * ObjectsFindManager::TreeObject::GetUserData()
  232. {
  233. return userData;
  234. }
  235. //Установить матрицу
  236. void ObjectsFindManager::TreeObject::SetMatrix(const Matrix & mtx)
  237. {
  238. #ifdef ENABLE_NAN_CHECK
  239. #ifndef STOP_DEBUG
  240. if(_isnan(mtx.pos.x) || _isnan(mtx.pos.y) || _isnan(mtx.pos.z) ||
  241. _isnan(mtx.vx.x) || _isnan(mtx.vx.y) || _isnan(mtx.vx.z) ||
  242. _isnan(mtx.vy.x) || _isnan(mtx.vy.y) || _isnan(mtx.vy.z) ||
  243. _isnan(mtx.vz.x) || _isnan(mtx.vz.y) || _isnan(mtx.vz.z))
  244. {
  245. api->Trace("%x, matrix = pos(%f, %f, %f), 3x3 = (%f, %f, %f, %f, %f, %f, %f, %f, %f)", this, mtx.pos.x, mtx.pos.y, mtx.pos.z, mtx.vx.x, mtx.vx.y, mtx.vx.z, mtx.vy.x, mtx.vy.y, mtx.vy.z, mtx.vz.x, mtx.vz.y, mtx.vz.z);
  246. #ifdef ENABLE_NAN_STOP
  247. Assert(false);
  248. #endif
  249. return;
  250. }
  251. #endif
  252. #endif
  253. matrix = mtx;
  254. SetToUpdate();
  255. }
  256. //Получить матрицу
  257. const Matrix & ObjectsFindManager::TreeObject::GetMatrix() const
  258. {
  259. return matrix;
  260. }
  261. //Установить локальную позицию описывающего бокса
  262. void ObjectsFindManager::TreeObject::SetBoxCenter(float centerX, float centerY, float centerZ)
  263. {
  264. #ifdef ENABLE_NAN_CHECK
  265. #ifndef STOP_DEBUG
  266. if(_isnan(centerX) || _isnan(centerY) || _isnan(centerZ))
  267. {
  268. api->Trace("%x, ObjectsFindManager::TreeObject::SetBoxCenter(%f, %f, %f)", this, centerX, centerY, centerZ);
  269. #ifdef ENABLE_NAN_STOP
  270. Assert(false);
  271. #endif
  272. return;
  273. }
  274. #endif
  275. #endif
  276. center.x = centerX;
  277. center.y = centerY;
  278. center.z = centerZ;
  279. SetToUpdate();
  280. }
  281. //Установить размер описывающего бокса
  282. void ObjectsFindManager::TreeObject::SetBoxSize(float sizeX, float sizeY, float sizeZ)
  283. {
  284. #ifdef ENABLE_NAN_CHECK
  285. #ifndef STOP_DEBUG
  286. if(_isnan(sizeX) || _isnan(sizeY) || _isnan(sizeZ))
  287. {
  288. api->Trace("%x, ObjectsFindManager::TreeObject::SetBoxSize(%f, %f, %f)", this, sizeX, sizeY, sizeZ);
  289. #ifdef ENABLE_NAN_STOP
  290. Assert(false);
  291. #endif
  292. return;
  293. }
  294. #endif
  295. #endif
  296. size.x = sizeX;
  297. size.y = sizeY;
  298. size.z = sizeZ;
  299. SetToUpdate();
  300. }
  301. //Получить размеры коробки OBB
  302. const Vector & ObjectsFindManager::TreeObject::GetBoxSize()
  303. {
  304. return size;
  305. }
  306. //Получить центр OBB
  307. const Vector & ObjectsFindManager::TreeObject::GetBoxCenter()
  308. {
  309. return center;
  310. }
  311. //Получить квадрад, занимаемый на дереве
  312. bool ObjectsFindManager::TreeObject::GetQTAbb(Vector & minAbb, Vector & maxAbb)
  313. {
  314. if(CheckAbb())
  315. {
  316. minAbb.x = (float)abb.minX;
  317. minAbb.y = 0.0f;
  318. minAbb.z = (float)abb.minZ;
  319. maxAbb.x = (float)abb.maxX;
  320. maxAbb.y = 0.0f;
  321. maxAbb.z = (float)abb.maxZ;
  322. return true;
  323. }
  324. return false;
  325. }
  326. //Следующий в списке нода
  327. __forceinline ObjectsFindManager::TreeObject * ObjectsFindManager::TreeObject::NextInNode()
  328. {
  329. return nextInNode;
  330. }
  331. //Следующий в мэнеджера списке
  332. __forceinline ObjectsFindManager::TreeObject * ObjectsFindManager::TreeObject::NextInList()
  333. {
  334. return nextInList;
  335. }
  336. //Получить текущий abb
  337. __forceinline const ObjectsFindManager::Abb & ObjectsFindManager::TreeObject::GetAbb()
  338. {
  339. return abb;
  340. }
  341. //Получить нод
  342. __forceinline ObjectsFindManager::Node * ObjectsFindManager::TreeObject::GetNode()
  343. {
  344. return node;
  345. }
  346. //Поставить в список обновления
  347. __forceinline void ObjectsFindManager::TreeObject::SetToUpdate()
  348. {
  349. flags &= ~(f_invalidateAbb | f_isUpdatedAbb);
  350. if(flags & f_active)
  351. {
  352. //Встанем в очередь обновления
  353. MoveToUpdateList();
  354. }
  355. }
  356. //Проверить и если надо пересчитать бокс
  357. __forceinline bool ObjectsFindManager::TreeObject::CheckAbb()
  358. {
  359. if((flags & f_isUpdatedAbb) == 0)
  360. {
  361. Vector min, max;
  362. Box::FindABBforOBB(matrix, center - size*0.5f, center + size*0.5f, min, max, false);
  363. bool inRange = abb.Set(min, max, false);
  364. /*
  365. #ifndef STOP_ASSERTS
  366. if(abb.AssertInRange("ObjectsFindManager::TreeObject::CheckAbb - 2", true))
  367. {
  368. api->Trace("object = %x", this);
  369. api->Trace("f_active = %i", (flags & f_active) != 0);
  370. api->Trace("f_isUpdatedAbb = %i", (flags & f_isUpdatedAbb) != 0);
  371. api->Trace("f_inUpdateList = %i", (flags & f_inUpdateList) != 0);
  372. api->Trace("f_inInactiveList = %i", (flags & f_inInactiveList) != 0);
  373. api->Trace("f_invalidateAbb = %i", (flags & f_invalidateAbb) != 0);
  374. api->Trace("f_deleted = %i", (flags & f_deleted) != 0);
  375. api->Trace("center = %f, %f, %f", center.x, center.y, center.z);
  376. api->Trace("size = %f, %f, %f", size.x, size.y, size.z);
  377. api->Trace("matrix = pos(%f, %f, %f), 3x3 = (%f, %f, %f, %f, %f, %f, %f, %f, %f)", matrix.pos.x, matrix.pos.y, matrix.pos.z, matrix.vx.x, matrix.vx.y, matrix.vx.z, matrix.vy.x, matrix.vy.y, matrix.vy.z, matrix.vz.x, matrix.vz.y, matrix.vz.z);
  378. api->Trace("CheckAbb: min = %f, %f; max = %f, %f", min.x, min.z, max.x, max.z);
  379. Assert(false);
  380. }
  381. #endif
  382. */
  383. flags |= f_isUpdatedAbb | f_invalidateAbb;
  384. if(inRange)
  385. {
  386. flags &= ~f_invalidateAbb;
  387. }
  388. }
  389. return (flags & f_invalidateAbb) == 0;
  390. }
  391. //Добавить себя в список нода
  392. __forceinline void ObjectsFindManager::TreeObject::AddToNode(Node * n)
  393. {
  394. Assert(n);
  395. RemoveFromNode();
  396. nextInNode = n->first;
  397. if(nextInNode)
  398. {
  399. nextInNode->prevInNode = this;
  400. }
  401. prevInNode = null;
  402. n->first = this;
  403. n->count++;
  404. node = n;
  405. }
  406. //Удалить себя из списка нода
  407. __forceinline void ObjectsFindManager::TreeObject::RemoveFromNode()
  408. {
  409. if(node)
  410. {
  411. if(nextInNode)
  412. {
  413. nextInNode->prevInNode = prevInNode;
  414. }
  415. if(prevInNode)
  416. {
  417. prevInNode->nextInNode = nextInNode;
  418. prevInNode = null;
  419. }else{
  420. Assert(node->first == this);
  421. node->first = nextInNode;
  422. }
  423. nextInNode = null;
  424. node->count--;
  425. Assert(node->count >= 0);
  426. node = null;
  427. }
  428. }
  429. //Поместить объект в список обновления
  430. __forceinline void ObjectsFindManager::TreeObject::MoveToUpdateList()
  431. {
  432. if(flags & f_inInactiveList)
  433. {
  434. Assert((flags & f_inUpdateList) == 0);
  435. RemoveFromList(mng->firstInactive);
  436. flags &= ~f_inInactiveList;
  437. }
  438. if((flags & f_inUpdateList) == 0)
  439. {
  440. AddToList(mng->firstUpdate);
  441. flags |= f_inUpdateList;
  442. }
  443. }
  444. //Поместить объект в список неактивных
  445. __forceinline void ObjectsFindManager::TreeObject::MoveToInactiveList()
  446. {
  447. if(flags & f_inUpdateList)
  448. {
  449. Assert((flags & f_inInactiveList) == 0);
  450. RemoveFromList(mng->firstUpdate);
  451. flags &= ~f_inUpdateList;
  452. }
  453. if((flags & f_inInactiveList) == 0)
  454. {
  455. AddToList(mng->firstInactive);
  456. flags |= f_inInactiveList;
  457. }
  458. }
  459. //Удалить из списков
  460. __forceinline void ObjectsFindManager::TreeObject::RemoveFromLists()
  461. {
  462. if(flags & f_inInactiveList)
  463. {
  464. Assert((flags & f_inUpdateList) == 0);
  465. RemoveFromList(mng->firstInactive);
  466. flags &= ~f_inInactiveList;
  467. }
  468. if(flags & f_inUpdateList)
  469. {
  470. Assert((flags & f_inInactiveList) == 0);
  471. RemoveFromList(mng->firstUpdate);
  472. flags &= ~f_inUpdateList;
  473. }
  474. }
  475. //Добавить в список
  476. __forceinline void ObjectsFindManager::TreeObject::AddToList(TreeObject * & first)
  477. {
  478. nextInList = first;
  479. if(nextInList)
  480. {
  481. nextInList->prevInList = this;
  482. }
  483. prevInList = null;
  484. first = this;
  485. }
  486. //Удалить из списка
  487. void ObjectsFindManager::TreeObject::RemoveFromList(TreeObject * & first)
  488. {
  489. if(nextInList)
  490. {
  491. nextInList->prevInList = prevInList;
  492. }
  493. if(prevInList)
  494. {
  495. prevInList->nextInList = nextInList;
  496. prevInList = null;
  497. }else{
  498. Assert(first == this);
  499. first = nextInList;
  500. }
  501. nextInList = null;
  502. }
  503. //Шагнуть по списку обновления
  504. __forceinline ObjectsFindManager::TreeObject * ObjectsFindManager::TreeObject::ExtractFirstFromUpdateList()
  505. {
  506. Assert(!prevInList);
  507. TreeObject * obj = nextInList;
  508. if(nextInList)
  509. {
  510. nextInList->prevInList = null;
  511. }
  512. nextInList = null;
  513. Assert(flags & f_inUpdateList);
  514. flags &= ~f_inUpdateList;
  515. return obj;
  516. }
  517. //Создать объект дерева
  518. __forceinline ObjectsFindManager::TreeObject * ObjectsFindManager::TreeObject::Create(ObjectsFindManager * manager, MissionObject * mo)
  519. {
  520. Assert(ObjectsFindManagerStorage::ptr);
  521. dword code;
  522. void * ptr = ObjectsFindManagerStorage::ptr->objects.Alloc(code);
  523. TreeObject * obj = new('a', ptr) TreeObject(mo, manager);
  524. obj->pullCode = code;
  525. return obj;
  526. }
  527. //Удалить объект дерева
  528. __forceinline void ObjectsFindManager::TreeObject::Delete(TreeObject * obj)
  529. {
  530. Assert(ObjectsFindManagerStorage::ptr);
  531. ObjectsFindManagerStorage::ptr->objects.Delete(obj->pullCode);
  532. }
  533. //============================================================================================
  534. //Node
  535. //============================================================================================
  536. __forceinline ObjectsFindManager::Node::Node(const Abb & nodeABB)
  537. {
  538. abb = nodeABB;
  539. cx = (abb.minX + abb.maxX + 1)/2;
  540. cz = (abb.minZ + abb.maxZ + 1)/2;
  541. child[s_minx_minz] = null;
  542. child[s_maxx_minz] = null;
  543. child[s_minx_maxz] = null;
  544. child[s_maxx_maxz] = null;
  545. parent = null;
  546. first = null;
  547. count = 0;
  548. pullCode = 0;
  549. }
  550. __forceinline ObjectsFindManager::Node::~Node()
  551. {
  552. Assert(false);
  553. }
  554. //Найти объекты, касающиеся abb
  555. void ObjectsFindManager::Node::FindObjects(const Abb & checkAbb, array<IMissionQTObject *> & list)
  556. {
  557. if(checkAbb.IsIntersection(abb))
  558. {
  559. //Объекты
  560. for(TreeObject * obj = first; obj; obj = obj->NextInNode())
  561. {
  562. if(checkAbb.IsIntersection(obj->GetAbb()))
  563. {
  564. list.Add(obj);
  565. }
  566. }
  567. //Дети
  568. if(child)
  569. {
  570. if(child[s_minx_minz])
  571. {
  572. child[s_minx_minz]->FindObjects(checkAbb, list);
  573. }
  574. if(child[s_maxx_minz])
  575. {
  576. child[s_maxx_minz]->FindObjects(checkAbb, list);
  577. }
  578. if(child[s_minx_maxz])
  579. {
  580. child[s_minx_maxz]->FindObjects(checkAbb, list);
  581. }
  582. if(child[s_maxx_maxz])
  583. {
  584. child[s_maxx_maxz]->FindObjects(checkAbb, list);
  585. }
  586. }
  587. }
  588. }
  589. //Получить нод для размещения объекта с заданным abb
  590. ObjectsFindManager::Node * ObjectsFindManager::Node::GetTreeNode(const Abb & objAbb)
  591. {
  592. //Уже точно известно что objAbb внутри данного нода, смотрим на попадание в детей
  593. if(objAbb.maxX < cx)
  594. {
  595. //Объект лежит полностью в левой половине нода
  596. if(objAbb.maxZ < cz)
  597. {
  598. //Объект лежит полностью в левой-задней половине нода
  599. if(child[s_minx_minz]) return child[s_minx_minz]->GetTreeNode(objAbb);
  600. //Если объектов на ноде мало, то не рыпаемся
  601. if(count < maxObjectsPerNode) return this;
  602. //Пробуем углубляться
  603. return AddChild(s_minx_minz, abb.minX, cx - 1, abb.minZ, cz - 1);
  604. }else
  605. if(objAbb.minZ >= cz)
  606. {
  607. //Объект лежит полностью в левой-передней половине нода
  608. if(child[s_minx_maxz]) return child[s_minx_maxz]->GetTreeNode(objAbb);
  609. //Если объектов на ноде мало, то не рыпаемся
  610. if(count < maxObjectsPerNode) return this;
  611. //Пробуем углубляться
  612. return AddChild(s_minx_maxz, abb.minX, cx - 1, cz, abb.maxZ);
  613. }
  614. }else
  615. if(objAbb.minX >= cx)
  616. {
  617. //Объект лежит полностью в правой половине нода
  618. if(objAbb.maxZ < cz)
  619. {
  620. //Объект лежит полностью в правой-задней половине нода
  621. if(child[s_maxx_minz]) return child[s_maxx_minz]->GetTreeNode(objAbb);
  622. //Если объектов на ноде мало, то не рыпаемся
  623. if(count < maxObjectsPerNode) return this;
  624. //Пробуем углубляться
  625. return AddChild(s_maxx_minz, cx, abb.maxX, abb.minZ, cz - 1);
  626. }else
  627. if(objAbb.minZ >= cz)
  628. {
  629. //Объект лежит полностью в правой-передней половине нода
  630. if(child[s_maxx_maxz]) return child[s_maxx_maxz]->GetTreeNode(objAbb);
  631. //Если объектов на ноде мало, то не рыпаемся
  632. if(count < maxObjectsPerNode) return this;
  633. //Пробуем углубляться
  634. return AddChild(s_maxx_maxz, cx, abb.maxX, cz, abb.maxZ);
  635. }
  636. }
  637. //Объект пересекает границы детей и не может быть положен глубже
  638. return this;
  639. }
  640. //Получить нод для размещения объекта с заданным abb
  641. __forceinline ObjectsFindManager::Node * ObjectsFindManager::Node::AddChild(long index, long abb_minX, long abb_maxX, long abb_minZ, long abb_maxZ)
  642. {
  643. if(abb_maxX - abb_minX >= minNodeSizeForSplit && abb_maxZ - abb_minZ >= minNodeSizeForSplit)
  644. {
  645. //Размеры позволяют создать ребёнка
  646. Node * n = Create(Abb(abb_minX, abb_maxX, abb_minZ, abb_maxZ));
  647. Assert(!child[index]);
  648. child[index] = n;
  649. n->parent = this;
  650. //Маркируем объекты что необходимо будет обновиться объектам
  651. for(TreeObject * obj = first; obj; obj = obj->NextInNode())
  652. {
  653. obj->SetToUpdate();
  654. }
  655. return n;
  656. }
  657. return this;
  658. }
  659. //Нарисовать узел, детей и объекты
  660. void ObjectsFindManager::Node::Draw(IRender * render, dword level, float levelScale)
  661. {
  662. #ifndef STOP_DEBUG
  663. static const Vector endAbb(0.99999f, 0.0f, 0.99999f);
  664. //Рисуем детей
  665. for(dword i = 0; i < s_numChilds; i++)
  666. {
  667. if(child[i])
  668. {
  669. child[i]->Draw(render, level + 1, levelScale);
  670. }
  671. }
  672. //Рисуем себя
  673. float flevel = level*levelScale;
  674. Vector vmin(float(abb.minX), (parent ? level - 1 : level)*levelScale, float(abb.minZ));
  675. Vector vmax(float(abb.maxX), flevel, float(abb.maxZ));
  676. render->DrawBox(vmin, vmax + endAbb, Matrix(), first ? 0xff00ff00 : 0xff0000ff);
  677. //Рисуем объекты
  678. for(TreeObject * obj = first; obj; obj = obj->NextInNode())
  679. {
  680. const Matrix & mtx = obj->GetMatrix();
  681. //Рисуем мировой ящик объекта
  682. Vector vmin = obj->GetBoxCenter() - obj->GetBoxSize()*0.5f;
  683. Vector vmax = obj->GetBoxCenter() + obj->GetBoxSize()*0.5f;
  684. render->DrawBox(vmin, vmax + endAbb, mtx, 0xffffff00);
  685. Vector worldCenter = mtx*((vmin + vmax)*0.5f);
  686. //Рисуем квадрат на дереве
  687. Vector nodeCenter;
  688. if(obj->GetQTAbb(vmin, vmax))
  689. {
  690. vmin.y = flevel;
  691. vmax.y = flevel;
  692. vmax += endAbb;
  693. render->DrawBox(vmin, vmax, Matrix(), 0xff909f20);
  694. nodeCenter = (vmin + vmax)*0.5f;
  695. render->Print(nodeCenter, 30.0f, 0.0f, 0xff909f20, "%u", level);
  696. }else{
  697. nodeCenter = worldCenter;
  698. nodeCenter.y = flevel;
  699. }
  700. //Линия до нода
  701. render->DrawLine(nodeCenter, 0xff0000ff, worldCenter, 0xffffff00);
  702. //Подпись
  703. render->Print(worldCenter, 100000.0f, 0.0f, 0xff00ff00, "MO: %s%s, 0x%.8x",
  704. obj->GetMissionObject().GetObjectID().c_str(),
  705. obj->CheckAbb() ? "" : " [invalidate box]",
  706. obj);
  707. }
  708. #endif
  709. }
  710. //Создать нод
  711. __forceinline ObjectsFindManager::Node * ObjectsFindManager::Node::Create(const Abb & nodeABB)
  712. {
  713. Assert(ObjectsFindManagerStorage::ptr);
  714. dword code;
  715. void * ptr = ObjectsFindManagerStorage::ptr->nodes.Alloc(code);
  716. Node * n = new('a', ptr) Node(nodeABB);
  717. n->pullCode = code;
  718. return n;
  719. }
  720. //Удалить нод
  721. void ObjectsFindManager::Node::Delete(Node * n)
  722. {
  723. if(!n) return;
  724. Assert(ObjectsFindManagerStorage::ptr);
  725. //Удаляем детей
  726. Delete(n->child[s_minx_minz]);
  727. Delete(n->child[s_maxx_minz]);
  728. Delete(n->child[s_minx_maxz]);
  729. Delete(n->child[s_maxx_maxz]);
  730. //Отписываем от нода объекты
  731. while(n->first)
  732. {
  733. n->first->RemoveFromNode();
  734. }
  735. //Удаляем себя
  736. ObjectsFindManagerStorage::ptr->nodes.Delete(n->pullCode);
  737. }
  738. //Вывести ветку в лог
  739. void ObjectsFindManager::Node::Dump(dword offset = 0)
  740. {
  741. #ifndef STOP_DEBUG
  742. char buffer[256];
  743. memset(buffer, ' ', sizeof(buffer));
  744. if(offset > sizeof(buffer) - 1) offset = sizeof(buffer) - 1;
  745. buffer[offset] = 0;
  746. abb.LogOut(buffer);
  747. api->Trace("%sCenter: (x: %i, z: %i)", buffer, cx, cz);
  748. api->Trace("%sObjects count: %i", buffer, count);
  749. const char * names[4];
  750. names[s_minx_minz] = "s_minx_minz";
  751. names[s_maxx_minz] = "s_maxx_minz";
  752. names[s_minx_maxz] = "s_minx_maxz";
  753. names[s_maxx_maxz] = "s_maxx_maxz";
  754. for(long i = 0; i < 4; i++)
  755. {
  756. if(child[i])
  757. {
  758. api->Trace("%s%s = ", buffer, names[i]);
  759. api->Trace("%s{", buffer);
  760. child[i]->Dump(offset + 2);
  761. api->Trace("%s", buffer);
  762. api->Trace("%s}", buffer);
  763. }else{
  764. api->Trace("%s%s = null", buffer, names[i]);
  765. }
  766. }
  767. #endif
  768. }
  769. //============================================================================================
  770. //ObjectsFindManager
  771. //============================================================================================
  772. ObjectsFindManager::ObjectsFindManager()
  773. {
  774. root = null;
  775. firstUpdate = null;
  776. firstInactive = null;
  777. }
  778. ObjectsFindManager::~ObjectsFindManager()
  779. {
  780. if(root)
  781. {
  782. Node::Delete(root);
  783. root = null;
  784. }
  785. }
  786. //Создать объект в дереве
  787. IMissionQTObject * ObjectsFindManager::CreateObject(MissionObject * mo, const char * cppFile, long cppLine)
  788. {
  789. TreeObject * obj = TreeObject::Create(this, mo);
  790. obj->cppFile = cppFile;
  791. obj->cppLine = cppLine;
  792. return obj;
  793. }
  794. //Найти объекты, попадающие в область
  795. void ObjectsFindManager::FindObjects(const Vector & minVrt, const Vector & maxVrt, array<IMissionQTObject *> & list)
  796. {
  797. //Обновим дерево
  798. UpdateTree();
  799. //Получаем целочисленный объём
  800. Abb abb;
  801. abb.Set(minVrt, maxVrt, true);
  802. //Очистим список
  803. list.Empty();
  804. //Собираем попадающих в область
  805. if(!root) return;
  806. root->FindObjects(abb, list);
  807. }
  808. //Нарисовать дерево и подписать объекты
  809. void ObjectsFindManager::Draw(IRender * render, float levelScale)
  810. {
  811. #ifndef STOP_DEBUG
  812. //Обновим дерево
  813. UpdateTree();
  814. //Рисуем активные объекты
  815. if(root)
  816. {
  817. root->Draw(render, 0, levelScale);
  818. }
  819. //Пишем список неактивных объектов под 0
  820. if(firstInactive)
  821. {
  822. float h = 3.0f;
  823. float k = Clampf((h - render->GetView().GetCamPos().y)/h);
  824. dword color = (dword(k*255.0f) << 24) | 0x00ff4040;
  825. Vector drawPoint = Vector(0.0f, -1.0f, 0.0f);
  826. float line = 0.0f;
  827. float step = 1.25f;
  828. render->Print(drawPoint, 100000.0f, line, color, "Inactive list:");
  829. for(TreeObject * obj = firstInactive; obj; obj = obj->NextInList())
  830. {
  831. line += step;
  832. render->Print(drawPoint, 100000.0f, line, color, "MO: %s%s, 0x%.8x",
  833. obj->GetMissionObject().GetObjectID().c_str(),
  834. obj->CheckAbb() ? "" : " [invalidate box]",
  835. obj);
  836. }
  837. }
  838. #endif
  839. }
  840. //Вывести ноды дерева в лог
  841. void ObjectsFindManager::Dump()
  842. {
  843. #ifndef STOP_DEBUG
  844. //Обновим дерево
  845. UpdateTree();
  846. //Выводим в лог
  847. if(root)
  848. {
  849. root->Dump();
  850. }
  851. #endif
  852. }
  853. //Обновить дерево
  854. void ObjectsFindManager::UpdateTree()
  855. {
  856. //Проходим по списку объектов, ожидающих обновление
  857. while(firstUpdate)
  858. {
  859. TreeObject * obj = firstUpdate;
  860. //Исключим из списка
  861. firstUpdate = obj->ExtractFirstFromUpdateList();
  862. //Посчитаем границы объекта
  863. if(obj->CheckAbb())
  864. {
  865. const Abb & objAbb = obj->GetAbb();
  866. #ifndef STOP_ASSERTS
  867. objAbb.AssertInRange("ObjectsFindManager::UpdateTree");
  868. #endif
  869. //Надо подобрать объекту нод
  870. Node * n = obj->GetNode();
  871. if(n)
  872. {
  873. if(n->abb.IsInclude(objAbb))
  874. {
  875. n = n->GetTreeNode(objAbb);
  876. obj->AddToNode(n);
  877. }else{
  878. //Поднимаемся на верх
  879. n = n->parent;
  880. //Поднимаемся от нода, пока не начнём влазить
  881. while(n)
  882. {
  883. if(n->abb.IsInclude(objAbb))
  884. {
  885. break;
  886. }
  887. n = n->parent;
  888. }
  889. if(n)
  890. {
  891. //Добавляем
  892. n = n->GetTreeNode(objAbb);
  893. obj->AddToNode(n);
  894. continue;
  895. }
  896. }
  897. }
  898. //Надо добавлять начиная от корня дерева
  899. ExtrudeTree(objAbb);
  900. Assert(root);
  901. n = root->GetTreeNode(objAbb);
  902. Assert(n);
  903. obj->AddToNode(n);
  904. }else{
  905. //Объект имеет неправильный ящик
  906. obj->MoveToInactiveList();
  907. }
  908. }
  909. }
  910. //Расширить дерево до размеров включающих abb
  911. void ObjectsFindManager::ExtrudeTree(const Abb & abb)
  912. {
  913. if(root)
  914. {
  915. while(!root->abb.IsInclude(abb))
  916. {
  917. //Определяем размер стартового нода
  918. Abb newAbb(root->abb);
  919. long index = 0;
  920. if(newAbb.maxZ < abb.maxZ)
  921. {
  922. //Вперёд
  923. newAbb.maxZ += newAbb.maxZ - newAbb.minZ + 1;
  924. }else{
  925. //Назад
  926. newAbb.minZ -= newAbb.maxZ - newAbb.minZ + 1;
  927. index |= s_maxz_mask;
  928. }
  929. if(newAbb.maxX < abb.maxX)
  930. {
  931. //Вправо
  932. newAbb.maxX += newAbb.maxX - newAbb.minX + 1;
  933. }else{
  934. //Влево
  935. newAbb.minX -= newAbb.maxX - newAbb.minX + 1;
  936. index |= s_maxx_mask;
  937. }
  938. //Добавляем уровень иерархии
  939. Node * n = root;
  940. root = Node::Create(newAbb);
  941. root->child[index] = n;
  942. n->parent = root;
  943. //Проверить, чтобы при увеличении были правильные размеры ребёнка
  944. #ifndef STOP_DEBUG
  945. if(index & s_maxx_mask)
  946. {
  947. if(root->cx != root->child[index]->abb.minX)
  948. {
  949. abb.LogOut("ObjectsFindManager::Extrude ");
  950. root->Dump();
  951. Assert(root->cx == root->child[index]->abb.minX);
  952. }
  953. }else{
  954. if(root->cx != root->child[index]->abb.maxX + 1)
  955. {
  956. abb.LogOut("ObjectsFindManager::Extrude ");
  957. root->Dump();
  958. Assert(root->cx == root->child[index]->abb.maxX + 1);
  959. }
  960. }
  961. if(index & s_maxz_mask)
  962. {
  963. if(root->cz != root->child[index]->abb.minZ)
  964. {
  965. abb.LogOut("ObjectsFindManager::Extrude ");
  966. root->Dump();
  967. Assert(root->cz == root->child[index]->abb.minZ);
  968. }
  969. }else{
  970. if(root->cz != root->child[index]->abb.maxZ + 1)
  971. {
  972. abb.LogOut("ObjectsFindManager::Extrude ");
  973. root->Dump();
  974. Assert(root->cz == root->child[index]->abb.maxZ + 1);
  975. }
  976. }
  977. #endif
  978. }
  979. }else{
  980. //Добавляем квадратный нод
  981. float centerX = (abb.minX + abb.maxX)*0.5f;
  982. float centerZ = (abb.minZ + abb.maxZ)*0.5f;
  983. long dX = abb.maxX - abb.minX;
  984. long dZ = abb.maxZ - abb.minZ;
  985. float size = (coremax(dX, dZ))*0.5f + 0.999999f;
  986. Abb quadAbb;
  987. quadAbb.minX = long(centerX - size);
  988. quadAbb.maxX = long(centerX + size);
  989. quadAbb.minZ = long(centerZ - size);
  990. quadAbb.maxZ = long(centerZ + size);
  991. root = Node::Create(quadAbb);
  992. }
  993. }
  994. //============================================================================================
  995. //ObjectsFindManagerStorage
  996. //============================================================================================
  997. CREATE_SERVICE(ObjectsFindManagerStorage, 100000)
  998. ObjectsFindManagerStorage * ObjectsFindManagerStorage::ptr = null;
  999. ObjectsFindManagerStorage::ObjectsFindManagerStorage()
  1000. {
  1001. Assert(!ptr);
  1002. ptr = this;
  1003. }
  1004. ObjectsFindManagerStorage::~ObjectsFindManagerStorage()
  1005. {
  1006. Assert(ptr == this);
  1007. ptr = null;
  1008. nodes.Clear();
  1009. objects.Clear();
  1010. }