DetourNode.cpp 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 "DetourNode.h"
  19. #include "DetourAlloc.h"
  20. #include "DetourAssert.h"
  21. #include "DetourCommon.h"
  22. #include <string.h>
  23. #ifdef DT_POLYREF64
  24. // From Thomas Wang, https://gist.github.com/badboy/6267743
  25. inline unsigned int dtHashRef(dtPolyRef a)
  26. {
  27. a = (~a) + (a << 18); // a = (a << 18) - a - 1;
  28. a = a ^ (a >> 31);
  29. a = a * 21; // a = (a + (a << 2)) + (a << 4);
  30. a = a ^ (a >> 11);
  31. a = a + (a << 6);
  32. a = a ^ (a >> 22);
  33. return (unsigned int)a;
  34. }
  35. #else
  36. inline unsigned int dtHashRef(dtPolyRef a)
  37. {
  38. a += ~(a<<15);
  39. a ^= (a>>10);
  40. a += (a<<3);
  41. a ^= (a>>6);
  42. a += ~(a<<11);
  43. a ^= (a>>16);
  44. return (unsigned int)a;
  45. }
  46. #endif
  47. //////////////////////////////////////////////////////////////////////////////////////////
  48. dtNodePool::dtNodePool(int maxNodes, int hashSize) :
  49. m_nodes(0),
  50. m_first(0),
  51. m_next(0),
  52. m_maxNodes(maxNodes),
  53. m_hashSize(hashSize),
  54. m_nodeCount(0)
  55. {
  56. dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize);
  57. dtAssert(m_maxNodes > 0);
  58. m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
  59. m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
  60. m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM);
  61. dtAssert(m_nodes);
  62. dtAssert(m_next);
  63. dtAssert(m_first);
  64. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  65. memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes);
  66. }
  67. dtNodePool::~dtNodePool()
  68. {
  69. dtFree(m_nodes);
  70. dtFree(m_next);
  71. dtFree(m_first);
  72. }
  73. void dtNodePool::clear()
  74. {
  75. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  76. m_nodeCount = 0;
  77. }
  78. unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes)
  79. {
  80. int n = 0;
  81. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  82. dtNodeIndex i = m_first[bucket];
  83. while (i != DT_NULL_IDX)
  84. {
  85. if (m_nodes[i].id == id)
  86. {
  87. if (n >= maxNodes)
  88. return n;
  89. nodes[n++] = &m_nodes[i];
  90. }
  91. i = m_next[i];
  92. }
  93. return n;
  94. }
  95. dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state)
  96. {
  97. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  98. dtNodeIndex i = m_first[bucket];
  99. while (i != DT_NULL_IDX)
  100. {
  101. if (m_nodes[i].id == id && m_nodes[i].state == state)
  102. return &m_nodes[i];
  103. i = m_next[i];
  104. }
  105. return 0;
  106. }
  107. dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state)
  108. {
  109. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  110. dtNodeIndex i = m_first[bucket];
  111. dtNode* node = 0;
  112. while (i != DT_NULL_IDX)
  113. {
  114. if (m_nodes[i].id == id && m_nodes[i].state == state)
  115. return &m_nodes[i];
  116. i = m_next[i];
  117. }
  118. if (m_nodeCount >= m_maxNodes)
  119. return 0;
  120. i = (dtNodeIndex)m_nodeCount;
  121. m_nodeCount++;
  122. // Init node
  123. node = &m_nodes[i];
  124. node->pidx = 0;
  125. node->cost = 0;
  126. node->total = 0;
  127. node->id = id;
  128. node->state = state;
  129. node->flags = 0;
  130. m_next[i] = m_first[bucket];
  131. m_first[bucket] = i;
  132. return node;
  133. }
  134. //////////////////////////////////////////////////////////////////////////////////////////
  135. dtNodeQueue::dtNodeQueue(int n) :
  136. m_heap(0),
  137. m_capacity(n),
  138. m_size(0)
  139. {
  140. dtAssert(m_capacity > 0);
  141. m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM);
  142. dtAssert(m_heap);
  143. }
  144. dtNodeQueue::~dtNodeQueue()
  145. {
  146. dtFree(m_heap);
  147. }
  148. void dtNodeQueue::bubbleUp(int i, dtNode* node)
  149. {
  150. int parent = (i-1)/2;
  151. // note: (index > 0) means there is a parent
  152. while ((i > 0) && (m_heap[parent]->total > node->total))
  153. {
  154. m_heap[i] = m_heap[parent];
  155. i = parent;
  156. parent = (i-1)/2;
  157. }
  158. m_heap[i] = node;
  159. }
  160. void dtNodeQueue::trickleDown(int i, dtNode* node)
  161. {
  162. int child = (i*2)+1;
  163. while (child < m_size)
  164. {
  165. if (((child+1) < m_size) &&
  166. (m_heap[child]->total > m_heap[child+1]->total))
  167. {
  168. child++;
  169. }
  170. m_heap[i] = m_heap[child];
  171. i = child;
  172. child = (i*2)+1;
  173. }
  174. bubbleUp(i, node);
  175. }