GridSectorizer.cpp 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /*
  2. * Copyright (c) 2014, Oculus VR, Inc.
  3. * All rights reserved.
  4. *
  5. * This source code is licensed under the BSD-style license found in the
  6. * LICENSE file in the root directory of this source tree. An additional grant
  7. * of patent rights can be found in the PATENTS file in the same directory.
  8. *
  9. */
  10. #include "RakAssert.h"
  11. #include "GridSectorizer.h"
  12. //#include <stdlib.h>
  13. #include <math.h>
  14. GridSectorizer::GridSectorizer()
  15. {
  16. grid=0;
  17. }
  18. GridSectorizer::~GridSectorizer()
  19. {
  20. if (grid)
  21. RakNet::OP_DELETE_ARRAY(grid, _FILE_AND_LINE_);
  22. }
  23. void GridSectorizer::Init(const float _maxCellWidth, const float _maxCellHeight, const float minX, const float minY, const float maxX, const float maxY)
  24. {
  25. RakAssert(_maxCellWidth > 0.0f && _maxCellHeight > 0.0f);
  26. if (grid)
  27. RakNet::OP_DELETE_ARRAY(grid, _FILE_AND_LINE_);
  28. cellOriginX=minX;
  29. cellOriginY=minY;
  30. gridWidth=maxX-minX;
  31. gridHeight=maxY-minY;
  32. gridCellWidthCount=(int) ceil(gridWidth/_maxCellWidth);
  33. gridCellHeightCount=(int) ceil(gridHeight/_maxCellHeight);
  34. // Make the cells slightly smaller, so we allocate an extra unneeded cell if on the edge. This way we don't go outside the array on rounding errors.
  35. cellWidth=gridWidth/gridCellWidthCount;
  36. cellHeight=gridHeight/gridCellHeightCount;
  37. invCellWidth = 1.0f / cellWidth;
  38. invCellHeight = 1.0f / cellHeight;
  39. #ifdef _USE_ORDERED_LIST
  40. grid = RakNet::OP_NEW<DataStructures::OrderedList<void*, void*>>(gridCellWidthCount*gridCellHeightCount, _FILE_AND_LINE_ );
  41. DataStructures::OrderedList<void*,void*>::IMPLEMENT_DEFAULT_COMPARISON();
  42. #else
  43. grid = RakNet::OP_NEW_ARRAY<DataStructures::List<void*> >(gridCellWidthCount*gridCellHeightCount, _FILE_AND_LINE_ );
  44. #endif
  45. }
  46. void GridSectorizer::AddEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
  47. {
  48. RakAssert(cellWidth>0.0f);
  49. RakAssert(minX < maxX && minY < maxY);
  50. int xStart, yStart, xEnd, yEnd, xCur, yCur;
  51. xStart=WorldToCellXOffsetAndClamped(minX);
  52. yStart=WorldToCellYOffsetAndClamped(minY);
  53. xEnd=WorldToCellXOffsetAndClamped(maxX);
  54. yEnd=WorldToCellYOffsetAndClamped(maxY);
  55. for (xCur=xStart; xCur <= xEnd; ++xCur)
  56. {
  57. for (yCur=yStart; yCur <= yEnd; ++yCur)
  58. {
  59. #ifdef _USE_ORDERED_LIST
  60. grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
  61. #else
  62. grid[yCur*gridCellWidthCount+xCur].Insert(entry, _FILE_AND_LINE_);
  63. #endif
  64. }
  65. }
  66. }
  67. #ifdef _USE_ORDERED_LIST
  68. void GridSectorizer::RemoveEntry(void *entry, const float minX, const float minY, const float maxX, const float maxY)
  69. {
  70. RakAssert(cellWidth>0.0f);
  71. RakAssert(minX <= maxX && minY <= maxY);
  72. int xStart, yStart, xEnd, yEnd, xCur, yCur;
  73. xStart=WorldToCellXOffsetAndClamped(minX);
  74. yStart=WorldToCellYOffsetAndClamped(minY);
  75. xEnd=WorldToCellXOffsetAndClamped(maxX);
  76. yEnd=WorldToCellYOffsetAndClamped(maxY);
  77. for (xCur=xStart; xCur <= xEnd; ++xCur)
  78. {
  79. for (yCur=yStart; yCur <= yEnd; ++yCur)
  80. {
  81. grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
  82. }
  83. }
  84. }
  85. void GridSectorizer::MoveEntry(void *entry, const float sourceMinX, const float sourceMinY, const float sourceMaxX, const float sourceMaxY,
  86. const float destMinX, const float destMinY, const float destMaxX, const float destMaxY)
  87. {
  88. RakAssert(cellWidth>0.0f);
  89. RakAssert(sourceMinX < sourceMaxX && sourceMinY < sourceMaxY);
  90. RakAssert(destMinX < destMaxX && destMinY < destMaxY);
  91. if (PositionCrossesCells(sourceMinX, sourceMinY, destMinX, destMinY)==false &&
  92. PositionCrossesCells(destMinX, destMinY, destMinX, destMinY)==false)
  93. return;
  94. int xStartSource, yStartSource, xEndSource, yEndSource;
  95. int xStartDest, yStartDest, xEndDest, yEndDest;
  96. int xCur, yCur;
  97. xStartSource=WorldToCellXOffsetAndClamped(sourceMinX);
  98. yStartSource=WorldToCellYOffsetAndClamped(sourceMinY);
  99. xEndSource=WorldToCellXOffsetAndClamped(sourceMaxX);
  100. yEndSource=WorldToCellYOffsetAndClamped(sourceMaxY);
  101. xStartDest=WorldToCellXOffsetAndClamped(destMinX);
  102. yStartDest=WorldToCellYOffsetAndClamped(destMinY);
  103. xEndDest=WorldToCellXOffsetAndClamped(destMaxX);
  104. yEndDest=WorldToCellYOffsetAndClamped(destMaxY);
  105. // Remove source that is not in dest
  106. for (xCur=xStartSource; xCur <= xEndSource; ++xCur)
  107. {
  108. for (yCur=yStartSource; yCur <= yEndSource; ++yCur)
  109. {
  110. if (xCur < xStartDest || xCur > xEndDest ||
  111. yCur < yStartDest || yCur > yEndDest)
  112. {
  113. grid[yCur*gridCellWidthCount+xCur].RemoveIfExists(entry);
  114. }
  115. }
  116. }
  117. // Add dest that is not in source
  118. for (xCur=xStartDest; xCur <= xEndDest; ++xCur)
  119. {
  120. for (yCur=yStartDest; yCur <= yEndDest; ++yCur)
  121. {
  122. if (xCur < xStartSource || xCur > xEndSource ||
  123. yCur < yStartSource || yCur > yEndSource)
  124. {
  125. grid[yCur*gridCellWidthCount+xCur].Insert(entry,entry, true);
  126. }
  127. }
  128. }
  129. }
  130. #endif
  131. void GridSectorizer::GetEntries(DataStructures::List<void*>& intersectionList, const float minX, const float minY, const float maxX, const float maxY)
  132. {
  133. #ifdef _USE_ORDERED_LIST
  134. DataStructures::OrderedList<void*, void*>* cell;
  135. #else
  136. DataStructures::List<void*>* cell;
  137. #endif
  138. int xStart, yStart, xEnd, yEnd, xCur, yCur;
  139. unsigned index;
  140. xStart=WorldToCellXOffsetAndClamped(minX);
  141. yStart=WorldToCellYOffsetAndClamped(minY);
  142. xEnd=WorldToCellXOffsetAndClamped(maxX);
  143. yEnd=WorldToCellYOffsetAndClamped(maxY);
  144. intersectionList.Clear(true, _FILE_AND_LINE_);
  145. for (xCur=xStart; xCur <= xEnd; ++xCur)
  146. {
  147. for (yCur=yStart; yCur <= yEnd; ++yCur)
  148. {
  149. cell = grid+yCur*gridCellWidthCount+xCur;
  150. for (index=0; index < cell->Size(); ++index)
  151. intersectionList.Insert(cell->operator [](index), _FILE_AND_LINE_);
  152. }
  153. }
  154. }
  155. bool GridSectorizer::PositionCrossesCells(const float originX, const float originY, const float destinationX, const float destinationY) const
  156. {
  157. return originX/cellWidth!=destinationX/cellWidth || originY/cellHeight!=destinationY/cellHeight;
  158. }
  159. int GridSectorizer::WorldToCellX(const float input) const
  160. {
  161. return (int)((input-cellOriginX)*invCellWidth);
  162. }
  163. int GridSectorizer::WorldToCellY(const float input) const
  164. {
  165. return (int)((input-cellOriginY)*invCellHeight);
  166. }
  167. int GridSectorizer::WorldToCellXOffsetAndClamped(const float input) const
  168. {
  169. int cell=WorldToCellX(input);
  170. cell = cell > 0 ? cell : 0; // __max(cell,0);
  171. cell = gridCellWidthCount-1 < cell ? gridCellWidthCount-1 : cell; // __min(gridCellWidthCount-1, cell);
  172. return cell;
  173. }
  174. int GridSectorizer::WorldToCellYOffsetAndClamped(const float input) const
  175. {
  176. int cell=WorldToCellY(input);
  177. cell = cell > 0 ? cell : 0; // __max(cell,0);
  178. cell = gridCellHeightCount-1 < cell ? gridCellHeightCount-1 : cell; // __min(gridCellHeightCount-1, cell);
  179. return cell;
  180. }
  181. void GridSectorizer::Clear(void)
  182. {
  183. int cur;
  184. int count = gridCellWidthCount*gridCellHeightCount;
  185. for (cur=0; cur<count;cur++)
  186. grid[cur].Clear(true, _FILE_AND_LINE_);
  187. }
粤ICP备19079148号