DetourProximityGrid.cpp 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193
  1. //
  2. // Copyright (c) 2009-2010 Mikko Mononen memon@inside.org
  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. #include <string.h>
  19. #include <new>
  20. #include "DetourProximityGrid.h"
  21. #include "recast/Detour/DetourCommon.h"
  22. #include "recast/Detour/DetourMath.h"
  23. #include "recast/Detour/DetourAlloc.h"
  24. #include "recast/Detour/DetourAssert.h"
  25. dtProximityGrid* dtAllocProximityGrid()
  26. {
  27. void* mem = dtAlloc(sizeof(dtProximityGrid), DT_ALLOC_PERM);
  28. if (!mem) return 0;
  29. return new(mem) dtProximityGrid;
  30. }
  31. void dtFreeProximityGrid(dtProximityGrid* ptr)
  32. {
  33. if (!ptr) return;
  34. ptr->~dtProximityGrid();
  35. dtFree(ptr);
  36. }
  37. inline int hashPos2(int x, int y, int n)
  38. {
  39. return ((x*73856093) ^ (y*19349663)) & (n-1);
  40. }
  41. dtProximityGrid::dtProximityGrid() :
  42. m_cellSize(0),
  43. m_pool(0),
  44. m_poolHead(0),
  45. m_poolSize(0),
  46. m_buckets(0),
  47. m_bucketsSize(0)
  48. {
  49. }
  50. dtProximityGrid::~dtProximityGrid()
  51. {
  52. dtFree(m_buckets);
  53. dtFree(m_pool);
  54. }
  55. bool dtProximityGrid::init(const int poolSize, const float cellSize)
  56. {
  57. dtAssert(poolSize > 0);
  58. dtAssert(cellSize > 0.0f);
  59. m_cellSize = cellSize;
  60. m_invCellSize = 1.0f / m_cellSize;
  61. // Allocate hashs buckets
  62. m_bucketsSize = dtNextPow2(poolSize);
  63. m_buckets = (unsigned short*)dtAlloc(sizeof(unsigned short)*m_bucketsSize, DT_ALLOC_PERM);
  64. if (!m_buckets)
  65. return false;
  66. // Allocate pool of items.
  67. m_poolSize = poolSize;
  68. m_poolHead = 0;
  69. m_pool = (Item*)dtAlloc(sizeof(Item)*m_poolSize, DT_ALLOC_PERM);
  70. if (!m_pool)
  71. return false;
  72. clear();
  73. return true;
  74. }
  75. void dtProximityGrid::clear()
  76. {
  77. memset(m_buckets, 0xff, sizeof(unsigned short)*m_bucketsSize);
  78. m_poolHead = 0;
  79. m_bounds[0] = 0xffff;
  80. m_bounds[1] = 0xffff;
  81. m_bounds[2] = -0xffff;
  82. m_bounds[3] = -0xffff;
  83. }
  84. void dtProximityGrid::addItem(const unsigned short id,
  85. const float minx, const float miny,
  86. const float maxx, const float maxy)
  87. {
  88. const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
  89. const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
  90. const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
  91. const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
  92. m_bounds[0] = dtMin(m_bounds[0], iminx);
  93. m_bounds[1] = dtMin(m_bounds[1], iminy);
  94. m_bounds[2] = dtMax(m_bounds[2], imaxx);
  95. m_bounds[3] = dtMax(m_bounds[3], imaxy);
  96. for (int y = iminy; y <= imaxy; ++y)
  97. {
  98. for (int x = iminx; x <= imaxx; ++x)
  99. {
  100. if (m_poolHead < m_poolSize)
  101. {
  102. const int h = hashPos2(x, y, m_bucketsSize);
  103. const unsigned short idx = (unsigned short)m_poolHead;
  104. m_poolHead++;
  105. Item& item = m_pool[idx];
  106. item.x = (short)x;
  107. item.y = (short)y;
  108. item.id = id;
  109. item.next = m_buckets[h];
  110. m_buckets[h] = idx;
  111. }
  112. }
  113. }
  114. }
  115. int dtProximityGrid::queryItems(const float minx, const float miny,
  116. const float maxx, const float maxy,
  117. unsigned short* ids, const int maxIds) const
  118. {
  119. const int iminx = (int)dtMathFloorf(minx * m_invCellSize);
  120. const int iminy = (int)dtMathFloorf(miny * m_invCellSize);
  121. const int imaxx = (int)dtMathFloorf(maxx * m_invCellSize);
  122. const int imaxy = (int)dtMathFloorf(maxy * m_invCellSize);
  123. int n = 0;
  124. for (int y = iminy; y <= imaxy; ++y)
  125. {
  126. for (int x = iminx; x <= imaxx; ++x)
  127. {
  128. const int h = hashPos2(x, y, m_bucketsSize);
  129. unsigned short idx = m_buckets[h];
  130. while (idx != 0xffff)
  131. {
  132. Item& item = m_pool[idx];
  133. if ((int)item.x == x && (int)item.y == y)
  134. {
  135. // Check if the id exists already.
  136. const unsigned short* end = ids + n;
  137. unsigned short* i = ids;
  138. while (i != end && *i != item.id)
  139. ++i;
  140. // Item not found, add it.
  141. if (i == end)
  142. {
  143. if (n >= maxIds)
  144. return n;
  145. ids[n++] = item.id;
  146. }
  147. }
  148. idx = item.next;
  149. }
  150. }
  151. }
  152. return n;
  153. }
  154. int dtProximityGrid::getItemCountAt(const int x, const int y) const
  155. {
  156. int n = 0;
  157. const int h = hashPos2(x, y, m_bucketsSize);
  158. unsigned short idx = m_buckets[h];
  159. while (idx != 0xffff)
  160. {
  161. Item& item = m_pool[idx];
  162. if ((int)item.x == x && (int)item.y == y)
  163. n++;
  164. idx = item.next;
  165. }
  166. return n;
  167. }