DetourNode.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  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. inline unsigned int dtHashRef(dtPolyRef a)
  24. {
  25. a += ~(a<<15);
  26. a ^= (a>>10);
  27. a += (a<<3);
  28. a ^= (a>>6);
  29. a += ~(a<<11);
  30. a ^= (a>>16);
  31. return (unsigned int)a;
  32. }
  33. //////////////////////////////////////////////////////////////////////////////////////////
  34. dtNodePool::dtNodePool(int maxNodes, int hashSize) :
  35. m_nodes(0),
  36. m_first(0),
  37. m_next(0),
  38. m_maxNodes(maxNodes),
  39. m_hashSize(hashSize),
  40. m_nodeCount(0)
  41. {
  42. dtAssert(dtNextPow2(m_hashSize) == (unsigned int)m_hashSize);
  43. dtAssert(m_maxNodes > 0);
  44. m_nodes = (dtNode*)dtAlloc(sizeof(dtNode)*m_maxNodes, DT_ALLOC_PERM);
  45. m_next = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*m_maxNodes, DT_ALLOC_PERM);
  46. m_first = (dtNodeIndex*)dtAlloc(sizeof(dtNodeIndex)*hashSize, DT_ALLOC_PERM);
  47. dtAssert(m_nodes);
  48. dtAssert(m_next);
  49. dtAssert(m_first);
  50. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  51. memset(m_next, 0xff, sizeof(dtNodeIndex)*m_maxNodes);
  52. }
  53. dtNodePool::~dtNodePool()
  54. {
  55. dtFree(m_nodes);
  56. dtFree(m_next);
  57. dtFree(m_first);
  58. }
  59. void dtNodePool::clear()
  60. {
  61. memset(m_first, 0xff, sizeof(dtNodeIndex)*m_hashSize);
  62. m_nodeCount = 0;
  63. }
  64. dtNode* dtNodePool::findNode(dtPolyRef id)
  65. {
  66. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  67. dtNodeIndex i = m_first[bucket];
  68. while (i != DT_NULL_IDX)
  69. {
  70. if (m_nodes[i].id == id)
  71. return &m_nodes[i];
  72. i = m_next[i];
  73. }
  74. return 0;
  75. }
  76. dtNode* dtNodePool::getNode(dtPolyRef id)
  77. {
  78. unsigned int bucket = dtHashRef(id) & (m_hashSize-1);
  79. dtNodeIndex i = m_first[bucket];
  80. dtNode* node = 0;
  81. while (i != DT_NULL_IDX)
  82. {
  83. if (m_nodes[i].id == id)
  84. return &m_nodes[i];
  85. i = m_next[i];
  86. }
  87. if (m_nodeCount >= m_maxNodes)
  88. return 0;
  89. i = (dtNodeIndex)m_nodeCount;
  90. m_nodeCount++;
  91. // Init node
  92. node = &m_nodes[i];
  93. node->pidx = 0;
  94. node->cost = 0;
  95. node->total = 0;
  96. node->id = id;
  97. node->flags = 0;
  98. m_next[i] = m_first[bucket];
  99. m_first[bucket] = i;
  100. return node;
  101. }
  102. //////////////////////////////////////////////////////////////////////////////////////////
  103. dtNodeQueue::dtNodeQueue(int n) :
  104. m_heap(0),
  105. m_capacity(n),
  106. m_size(0)
  107. {
  108. dtAssert(m_capacity > 0);
  109. m_heap = (dtNode**)dtAlloc(sizeof(dtNode*)*(m_capacity+1), DT_ALLOC_PERM);
  110. dtAssert(m_heap);
  111. }
  112. dtNodeQueue::~dtNodeQueue()
  113. {
  114. dtFree(m_heap);
  115. }
  116. void dtNodeQueue::bubbleUp(int i, dtNode* node)
  117. {
  118. int parent = (i-1)/2;
  119. // note: (index > 0) means there is a parent
  120. while ((i > 0) && (m_heap[parent]->total > node->total))
  121. {
  122. m_heap[i] = m_heap[parent];
  123. i = parent;
  124. parent = (i-1)/2;
  125. }
  126. m_heap[i] = node;
  127. }
  128. void dtNodeQueue::trickleDown(int i, dtNode* node)
  129. {
  130. int child = (i*2)+1;
  131. while (child < m_size)
  132. {
  133. if (((child+1) < m_size) &&
  134. (m_heap[child]->total > m_heap[child+1]->total))
  135. {
  136. child++;
  137. }
  138. m_heap[i] = m_heap[child];
  139. i = child;
  140. child = (i*2)+1;
  141. }
  142. bubbleUp(i, node);
  143. }