DetourProximityGrid.cpp 4.7 KB

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