DetourNode.cpp 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. // pidx is special as 0 means "none" and 1 is the first node. For that reason
  58. // we have 1 fewer nodes available than the number of values it can contain.
  59. dtAssert(m_maxNodes > 0 && m_maxNodes <= DT_NULL_IDX && m_maxNodes <= (1 << DT_NODE_PARENT_BITS) - 1);
  60. m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
  61. m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
  62. m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM);
  63. dtAssert(m_nodes);
  64. dtAssert(m_next);
  65. dtAssert(m_first);
  66. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  67. memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes);
  68. }
  69. dtNodePool::~dtNodePool()
  70. {
  71. dtFree(m_nodes);
  72. dtFree(m_next);
  73. dtFree(m_first);
  74. }
  75. void dtNodePool::clear()
  76. {
  77. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  78. m_nodeCount = 0;
  79. }
  80. unsigned int dtNodePool::findNodes(dtPolyRef id, dtNode** nodes, const int maxNodes)
  81. {
  82. int n = 0;
  83. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  84. dtNodeIndex i = m_first[bucket];
  85. while (i != DT_NULL_IDX)
  86. {
  87. if (m_nodes[i].id == id)
  88. {
  89. if (n >= maxNodes)
  90. return n;
  91. nodes[n++] = &m_nodes[i];
  92. }
  93. i = m_next[i];
  94. }
  95. return n;
  96. }
  97. dtNode* dtNodePool::findNode(dtPolyRef id, unsigned char state)
  98. {
  99. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  100. dtNodeIndex i = m_first[bucket];
  101. while (i != DT_NULL_IDX)
  102. {
  103. if (m_nodes[i].id == id && m_nodes[i].state == state)
  104. return &m_nodes[i];
  105. i = m_next[i];
  106. }
  107. return 0;
  108. }
  109. dtNode* dtNodePool::getNode(dtPolyRef id, unsigned char state)
  110. {
  111. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  112. dtNodeIndex i = m_first[bucket];
  113. dtNode* node = 0;
  114. while (i != DT_NULL_IDX)
  115. {
  116. if (m_nodes[i].id == id && m_nodes[i].state == state)
  117. return &m_nodes[i];
  118. i = m_next[i];
  119. }
  120. if (m_nodeCount >= m_maxNodes)
  121. return 0;
  122. i = (dtNodeIndex)m_nodeCount;
  123. m_nodeCount++;
  124. // Init node
  125. node = &m_nodes[i];
  126. node->pidx = 0;
  127. node->cost = 0;
  128. node->total = 0;
  129. node->id = id;
  130. node->state = state;
  131. node->flags = 0;
  132. m_next[i] = m_first[bucket];
  133. m_first[bucket] = i;
  134. return node;
  135. }
  136. //////////////////////////////////////////////////////////////////////////////////////////
  137. dtNodeQueue::dtNodeQueue(int n) :
  138. m_heap(0),
  139. m_capacity(n),
  140. m_size(0)
  141. {
  142. dtAssert(m_capacity > 0);
  143. m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM);
  144. dtAssert(m_heap);
  145. }
  146. dtNodeQueue::~dtNodeQueue()
  147. {
  148. dtFree(m_heap);
  149. }
  150. void dtNodeQueue::bubbleUp(int i, dtNode* node)
  151. {
  152. int parent = (i-1)/2;
  153. // note: (index > 0) means there is a parent
  154. while ((i > 0) && (m_heap[parent]->total > node->total))
  155. {
  156. m_heap[i] = m_heap[parent];
  157. i = parent;
  158. parent = (i-1)/2;
  159. }
  160. m_heap[i] = node;
  161. }
  162. void dtNodeQueue::trickleDown(int i, dtNode* node)
  163. {
  164. int child = (i*2)+1;
  165. while (child < m_size)
  166. {
  167. if (((child+1) < m_size) &&
  168. (m_heap[child]->total > m_heap[child+1]->total))
  169. {
  170. child++;
  171. }
  172. m_heap[i] = m_heap[child];
  173. i = child;
  174. child = (i*2)+1;
  175. }
  176. bubbleUp(i, node);
  177. }