DetourNode.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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. #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. dtNode* dtNodePool::findNode(dtPolyRef id)
  79. {
  80. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  81. dtNodeIndex i = m_first[bucket];
  82. while (i != DT_NULL_IDX)
  83. {
  84. if (m_nodes[i].id == id)
  85. return &m_nodes[i];
  86. i = m_next[i];
  87. }
  88. return 0;
  89. }
  90. dtNode* dtNodePool::getNode(dtPolyRef id)
  91. {
  92. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  93. dtNodeIndex i = m_first[bucket];
  94. dtNode* node = 0;
  95. while (i != DT_NULL_IDX)
  96. {
  97. if (m_nodes[i].id == id)
  98. return &m_nodes[i];
  99. i = m_next[i];
  100. }
  101. if (m_nodeCount >= m_maxNodes)
  102. return 0;
  103. i = (dtNodeIndex)m_nodeCount;
  104. m_nodeCount++;
  105. // Init node
  106. node = &m_nodes[i];
  107. node->pidx = 0;
  108. node->cost = 0;
  109. node->total = 0;
  110. node->id = id;
  111. node->flags = 0;
  112. m_next[i] = m_first[bucket];
  113. m_first[bucket] = i;
  114. return node;
  115. }
  116. //////////////////////////////////////////////////////////////////////////////////////////
  117. dtNodeQueue::dtNodeQueue(int n) :
  118. m_heap(0),
  119. m_capacity(n),
  120. m_size(0)
  121. {
  122. dtAssert(m_capacity > 0);
  123. m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM);
  124. dtAssert(m_heap);
  125. }
  126. dtNodeQueue::~dtNodeQueue()
  127. {
  128. dtFree(m_heap);
  129. }
  130. void dtNodeQueue::bubbleUp(int i, dtNode* node)
  131. {
  132. int parent = (i-1)/2;
  133. // note: (index > 0) means there is a parent
  134. while ((i > 0) && (m_heap[parent]->total > node->total))
  135. {
  136. m_heap[i] = m_heap[parent];
  137. i = parent;
  138. parent = (i-1)/2;
  139. }
  140. m_heap[i] = node;
  141. }
  142. void dtNodeQueue::trickleDown(int i, dtNode* node)
  143. {
  144. int child = (i*2)+1;
  145. while (child < m_size)
  146. {
  147. if (((child+1) < m_size) &&
  148. (m_heap[child]->total > m_heap[child+1]->total))
  149. {
  150. child++;
  151. }
  152. m_heap[i] = m_heap[child];
  153. i = child;
  154. child = (i*2)+1;
  155. }
  156. bubbleUp(i, node);
  157. }