DetourProximityGrid.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  1. //
  2. // Copyright (c) 2009-2010 Mikko Mononen [email protected]
  3. //
  4. // This software is provided 'as-is', without any express or implied
  5. // warranty. In no event will the authors be held liable for any damages
  6. // arising from the use of this software.
  7. // Permission is granted to anyone to use this software for any purpose,
  8. // including commercial applications, and to alter it and redistribute it
  9. // freely, subject to the following restrictions:
  10. // 1. The origin of this software must not be misrepresented; you must not
  11. // claim that you wrote the original software. If you use this software
  12. // in a product, an acknowledgment in the product documentation would be
  13. // appreciated but is not required.
  14. // 2. Altered source versions must be plainly marked as such, and must not be
  15. // misrepresented as being the original software.
  16. // 3. This notice may not be removed or altered from any source distribution.
  17. //
  18. // Modified by cosmy1 for Urho3D
  19. #include <string.h>
  20. #include <new>
  21. #include "DetourProximityGrid.h"
  22. #include "DetourCommon.h"
  23. #include "DetourMath.h"
  24. #include "DetourAlloc.h"
  25. #include "DetourAssert.h"
  26. dtProximityGrid* dtAllocProximityGrid()
  27. {
  28. void* mem = dtAlloc(sizeof(dtProximityGrid), DT_ALLOC_PERM);
  29. if (!mem) return 0;
  30. return new(mem) dtProximityGrid;
  31. }
  32. void dtFreeProximityGrid(dtProximityGrid* ptr)
  33. {
  34. if (!ptr) return;
  35. ptr->~dtProximityGrid();
  36. dtFree(ptr);
  37. }
  38. inline int hashPos2(int x, int y, int n)
  39. {
  40. return ((x*73856093) ^ (y*19349663)) & (n-1);
  41. }
  42. // Urho3D: initialize all class members
  43. dtProximityGrid::dtProximityGrid() :
  44. m_maxItems(0),
  45. m_cellSize(0),
  46. m_pool(0),
  47. m_poolHead(0),
  48. m_poolSize(0),
  49. m_buckets(0),
  50. m_bucketsSize(0),
  51. m_invCellSize(0) // Urho3D
  52. {
  53. memset(&m_bounds, 0, sizeof(m_bounds)); // Urho3D
  54. }
  55. dtProximityGrid::~dtProximityGrid()
  56. {
  57. dtFree(m_buckets);
  58. dtFree(m_pool);
  59. }
  60. bool dtProximityGrid::init(const int poolSize, const float cellSize)
  61. {
  62. dtAssert(poolSize > 0);
  63. dtAssert(cellSize > 0.0f);
  64. m_cellSize = cellSize;
  65. m_invCellSize = 1.0f / m_cellSize;
  66. // Allocate hashs buckets
  67. m_bucketsSize = dtNextPow2(poolSize);
  68. m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM);
  69. if (!m_buckets)
  70. return false;
  71. // Allocate pool of items.
  72. m_poolSize = poolSize;
  73. m_poolHead = 0;
  74. m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM);
  75. if (!m_pool)
  76. return false;
  77. clear();
  78. return true;
  79. }
  80. void dtProximityGrid::clear()
  81. {
  82. memset(m_buckets, 0xff, sizeof(unsigned short)*m_bucketsSize);
  83. m_poolHead = 0;
  84. m_bounds[0] = 0xffff;
  85. m_bounds[1] = 0xffff;
  86. m_bounds[2] = -0xffff;
  87. m_bounds[3] = -0xffff;
  88. }
  89. void dtProximityGrid::addItem(const unsigned short id,
  90. const float minx, const float miny,
  91. const float maxx, const float maxy)
  92. {
  93. const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
  94. const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
  95. const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
  96. const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
  97. m_bounds[0] = dtMin(m_bounds[0], iminx);
  98. m_bounds[1] = dtMin(m_bounds[1], iminy);
  99. m_bounds[2] = dtMax(m_bounds[2], imaxx);
  100. m_bounds[3] = dtMax(m_bounds[3], imaxy);
  101. for (int y = iminy; y <= imaxy; ++y)
  102. {
  103. for (int x = iminx; x <= imaxx; ++x)
  104. {
  105. if (m_poolHead < m_poolSize)
  106. {
  107. const int h = hashPos2(x, y, m_bucketsSize);
  108. const unsigned short idx = (unsigned short)m_poolHead;
  109. m_poolHead++;
  110. Item& item = m_pool[idx];
  111. item.x = (short)x;
  112. item.y = (short)y;
  113. item.id = id;
  114. item.next = m_buckets[h];
  115. m_buckets[h] = idx;
  116. }
  117. }
  118. }
  119. }
  120. int dtProximityGrid::queryItems(const float minx, const float miny,
  121. const float maxx, const float maxy,
  122. unsigned short* ids, const int maxIds) const
  123. {
  124. const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
  125. const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
  126. const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
  127. const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
  128. int n = 0;
  129. for (int y = iminy; y <= imaxy; ++y)
  130. {
  131. for (int x = iminx; x <= imaxx; ++x)
  132. {
  133. const int h = hashPos2(x, y, m_bucketsSize);
  134. unsigned short idx = m_buckets[h];
  135. while (idx != 0xffff)
  136. {
  137. Item& item = m_pool[idx];
  138. if ((int)item.x == x && (int)item.y == y)
  139. {
  140. // Check if the id exists already.
  141. const unsigned short* end = ids + n;
  142. unsigned short* i = ids;
  143. while (i != end && *i != item.id)
  144. ++i;
  145. // Item not found, add it.
  146. if (i == end)
  147. {
  148. if (n >= maxIds)
  149. return n;
  150. ids[n++] = item.id;
  151. }
  152. }
  153. idx = item.next;
  154. }
  155. }
  156. }
  157. return n;
  158. }
  159. int dtProximityGrid::getItemCountAt(const int x, const int y) const
  160. {
  161. int n = 0;
  162. const int h = hashPos2(x, y, m_bucketsSize);
  163. unsigned short idx = m_buckets[h];
  164. while (idx != 0xffff)
  165. {
  166. Item& item = m_pool[idx];
  167. if ((int)item.x == x && (int)item.y == y)
  168. n++;
  169. idx = item.next;
  170. }
  171. return n;
  172. }