PageRenderTime 40ms CodeModel.GetById 10ms RepoModel.GetById 0ms app.codeStats 0ms

/BEPUphysics/BroadPhaseSystems/SortAndSweep/Grid2DSortAndSweepQueryAccelerator.cs

#
C# | 220 lines | 165 code | 26 blank | 29 comment | 34 complexity | 3883b4fcc83d2b314d06d220fc6219be MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using BEPUutilities;
  6. using BEPUphysics.BroadPhaseEntries;
  7. namespace BEPUphysics.BroadPhaseSystems.SortAndSweep
  8. {
  9. public class Grid2DSortAndSweepQueryAccelerator : IQueryAccelerator
  10. {
  11. Grid2DSortAndSweep owner;
  12. public Grid2DSortAndSweepQueryAccelerator(Grid2DSortAndSweep owner)
  13. {
  14. this.owner = owner;
  15. }
  16. /// <summary>
  17. /// Gets the broad phase associated with this query accelerator.
  18. /// </summary>
  19. public BroadPhase BroadPhase
  20. {
  21. get
  22. {
  23. return owner;
  24. }
  25. }
  26. public bool RayCast(Ray ray, IList<BroadPhaseEntry> outputIntersections)
  27. {
  28. throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate infinite ray casts. Consider using a broad phase which supports infinite tests, using a custom solution, or using a finite ray.");
  29. }
  30. public bool RayCast(Ray ray, float maximumLength, IList<BroadPhaseEntry> outputIntersections)
  31. {
  32. if (maximumLength == float.MaxValue)
  33. throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate infinite ray casts. Consider specifying a maximum length or using a broad phase which supports infinite ray casts.");
  34. //Use 2d line rasterization.
  35. //Compute the exit location in the cell.
  36. //Test against each bounding box up until the exit value is reached.
  37. float length = 0;
  38. Int2 cellIndex;
  39. Vector3 currentPosition = ray.Position;
  40. Grid2DSortAndSweep.ComputeCell(ref currentPosition, out cellIndex);
  41. while (true)
  42. {
  43. float cellWidth = 1 / Grid2DSortAndSweep.cellSizeInverse;
  44. float nextT; //Distance along ray to next boundary.
  45. float nextTy; //Distance along ray to next boundary along y axis.
  46. float nextTz; //Distance along ray to next boundary along z axis.
  47. //Find the next cell.
  48. if (ray.Direction.Y > 0)
  49. nextTy = ((cellIndex.Y + 1) * cellWidth - currentPosition.Y) / ray.Direction.Y;
  50. else if (ray.Direction.Y < 0)
  51. nextTy = ((cellIndex.Y) * cellWidth - currentPosition.Y) / ray.Direction.Y;
  52. else
  53. nextTy = 10e10f;
  54. if (ray.Direction.Z > 0)
  55. nextTz = ((cellIndex.Z + 1) * cellWidth - currentPosition.Z) / ray.Direction.Z;
  56. else if (ray.Direction.Z < 0)
  57. nextTz = ((cellIndex.Z) * cellWidth - currentPosition.Z) / ray.Direction.Z;
  58. else
  59. nextTz = 10e10f;
  60. bool yIsMinimum = nextTy < nextTz;
  61. nextT = yIsMinimum ? nextTy : nextTz;
  62. //Grab the cell that we are currently in.
  63. GridCell2D cell;
  64. if (owner.cellSet.TryGetCell(ref cellIndex, out cell))
  65. {
  66. float endingX;
  67. if(ray.Direction.X < 0)
  68. endingX = currentPosition.X;
  69. else
  70. endingX = currentPosition.X + ray.Direction.X * nextT;
  71. //To fully accelerate this, the entries list would need to contain both min and max interval markers.
  72. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list.
  73. //Consider some giant bounding box that spans the entire list.
  74. for (int i = 0; i < cell.entries.Count
  75. && cell.entries.Elements[i].item.boundingBox.Min.X <= endingX; i++) //TODO: Try additional x axis pruning?
  76. {
  77. var item = cell.entries.Elements[i].item;
  78. float t;
  79. if (ray.Intersects(ref item.boundingBox, out t) && t < maximumLength && !outputIntersections.Contains(item))
  80. {
  81. outputIntersections.Add(item);
  82. }
  83. }
  84. }
  85. //Move the position forward.
  86. length += nextT;
  87. if (length > maximumLength) //Note that this catches the case in which the ray is pointing right down the middle of a row (resulting in a nextT of 10e10f).
  88. break;
  89. Vector3 offset;
  90. Vector3.Multiply(ref ray.Direction, nextT, out offset);
  91. Vector3.Add(ref offset, ref currentPosition, out currentPosition);
  92. if (yIsMinimum)
  93. if (ray.Direction.Y < 0)
  94. cellIndex.Y -= 1;
  95. else
  96. cellIndex.Y += 1;
  97. else
  98. if (ray.Direction.Z < 0)
  99. cellIndex.Z -= 1;
  100. else
  101. cellIndex.Z += 1;
  102. }
  103. return outputIntersections.Count > 0;
  104. }
  105. public void GetEntries(BoundingBox boundingShape, IList<BroadPhaseEntry> overlaps)
  106. {
  107. //Compute the min and max of the bounding box.
  108. //Loop through the cells and select bounding boxes which overlap the x axis.
  109. Int2 min, max;
  110. Grid2DSortAndSweep.ComputeCell(ref boundingShape.Min, out min);
  111. Grid2DSortAndSweep.ComputeCell(ref boundingShape.Max, out max);
  112. for (int i = min.Y; i <= max.Y; i++)
  113. {
  114. for (int j = min.Z; j <= max.Z; j++)
  115. {
  116. //Grab the cell that we are currently in.
  117. Int2 cellIndex;
  118. cellIndex.Y = i;
  119. cellIndex.Z = j;
  120. GridCell2D cell;
  121. if (owner.cellSet.TryGetCell(ref cellIndex, out cell))
  122. {
  123. //To fully accelerate this, the entries list would need to contain both min and max interval markers.
  124. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list.
  125. //Consider some giant bounding box that spans the entire list.
  126. for (int k = 0; k < cell.entries.Count
  127. && cell.entries.Elements[k].item.boundingBox.Min.X <= boundingShape.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test.
  128. {
  129. bool intersects;
  130. var item = cell.entries.Elements[k].item;
  131. boundingShape.Intersects(ref item.boundingBox, out intersects);
  132. if (intersects && !overlaps.Contains(item))
  133. {
  134. overlaps.Add(item);
  135. }
  136. }
  137. }
  138. }
  139. }
  140. }
  141. public void GetEntries(BoundingSphere boundingShape, IList<BroadPhaseEntry> overlaps)
  142. {
  143. //Create a bounding box based on the bounding sphere.
  144. //Compute the min and max of the bounding box.
  145. //Loop through the cells and select bounding boxes which overlap the x axis.
  146. #if !WINDOWS
  147. Vector3 offset = new Vector3();
  148. #else
  149. Vector3 offset;
  150. #endif
  151. offset.X = boundingShape.Radius;
  152. offset.Y = offset.X;
  153. offset.Z = offset.Y;
  154. BoundingBox box;
  155. Vector3.Add(ref boundingShape.Center, ref offset, out box.Max);
  156. Vector3.Subtract(ref boundingShape.Center, ref offset, out box.Min);
  157. Int2 min, max;
  158. Grid2DSortAndSweep.ComputeCell(ref box.Min, out min);
  159. Grid2DSortAndSweep.ComputeCell(ref box.Max, out max);
  160. for (int i = min.Y; i <= max.Y; i++)
  161. {
  162. for (int j = min.Z; j <= max.Z; j++)
  163. {
  164. //Grab the cell that we are currently in.
  165. Int2 cellIndex;
  166. cellIndex.Y = i;
  167. cellIndex.Z = j;
  168. GridCell2D cell;
  169. if (owner.cellSet.TryGetCell(ref cellIndex, out cell))
  170. {
  171. //To fully accelerate this, the entries list would need to contain both min and max interval markers.
  172. //Since it only contains the sorted min intervals, we can't just start at a point in the middle of the list.
  173. //Consider some giant bounding box that spans the entire list.
  174. for (int k = 0; k < cell.entries.Count
  175. && cell.entries.Elements[k].item.boundingBox.Min.X <= box.Max.X; k++) //TODO: Try additional x axis pruning? A bit of optimization potential due to overlap with AABB test.
  176. {
  177. bool intersects;
  178. var item = cell.entries.Elements[k].item;
  179. item.boundingBox.Intersects(ref boundingShape, out intersects);
  180. if (intersects && !overlaps.Contains(item))
  181. {
  182. overlaps.Add(item);
  183. }
  184. }
  185. }
  186. }
  187. }
  188. }
  189. //public void GetEntries(BoundingFrustum boundingShape, IList<BroadPhaseEntry> overlaps)
  190. //{
  191. // throw new NotSupportedException("The Grid2DSortAndSweep broad phase cannot accelerate frustum tests. Consider using a broad phase which supports frustum tests or using a custom solution.");
  192. //}
  193. }
  194. }