All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
CollisionBvhIntersectionQueries.h
1 // Copyright eeGeo Ltd (2012-2014), All Rights Reserved
2 
3 #pragma once
4 
5 #include "Collision.h"
6 #include "VectorMath.h"
7 #include "CollisionBvh.h"
8 #include "RayNodeIntersectionResult.h"
9 #include "RayMeshIntersectionResult.h"
10 #include "CollisionBvhNodeIntersectionTests.h"
11 #include "ArrayAllocator.h"
12 #include "SkewedRay.h"
13 
14 
15 
16 #include <stack>
17 #include <vector>
18 
19 namespace Eegeo
20 {
21  namespace Collision
22  {
23  template <typename TOutputIter>
24  inline TOutputIter GetLeafNodesIntersectingRay(
25  const Eegeo::Collision::CollisionBvh& collisionBvh,
26  const Eegeo::v3& rayOrigin,
27  const Eegeo::v3& rayDirection,
28  TOutputIter rayNodeIntersectionResult);
29 
30  template <typename TOutputIter>
31  inline TOutputIter GetLeafNodesIntersectingLineSegment(const Eegeo::Collision::CollisionBvh& collisionBvh,
32  const Eegeo::v3& lineSegmentStart,
33  const Eegeo::v3& lineSegmentDirection,
34  float lineSegmentLength,
35  TOutputIter rayNodeIntersectionResult);
36 
37  template <typename TOutputIter>
38  inline TOutputIter GetLeafNodesIntersectingSkewedRay(
39  const Eegeo::Collision::CollisionBvh& collisionBvh,
40  const SkewedRay& skewedRay,
41  TOutputIter rayNodeIntersectionResult);
42 
43  template <typename TOutputIter>
44  inline TOutputIter GetLeafNodesIntersectingSkewedRayBruteForce(const Eegeo::Collision::CollisionBvh& collisionBvh,
45  const SkewedRay& skewedRay,
46  TOutputIter rayNodeIntersectionResult);
47 
48  template <typename TOutputIter>
49  inline TOutputIter GetTransformedLeafNodesIntersectingRay(
50  const Eegeo::Collision::CollisionBvh& collisionBvh,
51  const m44& inverseModelTransform,
52  const Eegeo::dv3& rayOriginEcef,
53  const Eegeo::dv3& rayDirectionEcef,
54  TOutputIter rayNodeIntersectionResults);
55 
56 
57 
58  RayMeshIntersectionResult RayMeshIntersection(const Eegeo::Collision::CollisionBvh& collisionBvh,
59  const Eegeo::Collision::CollisionBvhNode& leafNode,
60  const Eegeo::v3& rayOrigin,
61  const Eegeo::v3& rayDirection,
62  const float skewedParamScale);
63 
64  SkewedRay CalculateModelSpaceRay(
65  const dv3& rayOriginEcef,
66  const dv3& rayDirectionEcef,
67  const dv3& modelOriginEcef,
68  const m44& inverseModelTransform
69  );
70 
71 
72  SkewedRay CalcEnvironmentFlattenedSkewedRay(const v3& rayOrigin,
73  const v3& rayDirection,
74  const dv3& collisionBvhOriginEcef,
75  const float environmentFlatteningScale);
76 
77  SkewedRay CorrectInteriorRayForEnvironmentFlattening(const v3& rayOrigin,
78  const v3& rayDirection,
79  const dv3& collisionBvhOriginEcef,
80  const float environmentFlatteningScale,
81  const float terrainHeight);
82 
83  m33 CalcEnvironmentFlatteningTransform(const dv3& meshOrigin, const float environmentFlatteningScale);
84 
85 
86  namespace
87  {
88  template <typename T, int MaxStackSize>
89  struct TStackAllocatedStack
90  {
91  private:
92 #if defined(EEGEO_WIN) && !defined(NDEBUG)
93  typedef std::allocator<T> IntArrayStackAllocator;
94 #else
95  typedef Eegeo::Helpers::ArrayAllocator<T, MaxStackSize> IntArrayStackAllocator;
96 #endif
97  typedef std::vector<T, IntArrayStackAllocator> StackAllocatedVector;
98  public:
99  typedef std::stack<T, StackAllocatedVector> Type;
100  };
101 
102  typedef TStackAllocatedStack<int, 1024>::Type WorkspaceStack;
103 
104  template <typename TIntegerStack, typename TIntersectionTest, typename TResultPredicate, typename TOutIter>
105  inline TOutIter GetCollisionBvhLeafNodes(TIntegerStack& stack,
106  const Eegeo::Collision::CollisionBvh& collisionBvh,
107  TIntersectionTest intersectionTest,
108  TResultPredicate resultPredicate,
109  TOutIter outIterFirst)
110  {
111  Eegeo_ASSERT(stack.empty());
112  TOutIter outIter = outIterFirst;
113  if (collisionBvh.Nodes().empty())
114  return outIter;
115 
116  const int RootNodeIndex = 0;
117  stack.push(RootNodeIndex);
118 
119  const std::vector<Eegeo::Collision::CollisionBvhNode>& nodes = collisionBvh.Nodes();
120 
121  while (!stack.empty())
122  {
123  int candidateNodeIndex = stack.top();
124  stack.pop();
125 
126  const Eegeo::Collision::CollisionBvhNode& candidate = nodes[candidateNodeIndex];
127 
128  const typename TIntersectionTest::result_type& result = intersectionTest(candidate);
129  if ( resultPredicate(result))
130  {
131  if (candidate.IsLeafNode())
132  {
133  *outIter++ = result;
134  }
135  else
136  {
137  const int indexOffset = candidate.FirstChildIndex();
138  const int end = indexOffset + candidate.ChildCount();
139  for (int i = indexOffset ; i < end; ++i)
140  {
141  stack.push(i);
142  }
143  }
144  }
145  }
146 
147  return outIter;
148  }
149  }
150 
151  template <typename TOutputIter>
152  inline TOutputIter GetLeafNodesIntersectingRay(
153  const Eegeo::Collision::CollisionBvh& collisionBvh,
154  const Eegeo::v3& rayOrigin,
155  const Eegeo::v3& rayDirection,
156  TOutputIter rayNodeIntersectionResult)
157  {
158  const float skewedParamScale = 1.f;
159  BvhNodeRayIntersectionTest intersectionTest(collisionBvh, rayOrigin, rayDirection, skewedParamScale);
160  WorkspaceStack workspaceStack;
161 
162  return GetCollisionBvhLeafNodes(workspaceStack, collisionBvh, intersectionTest, BvhNodeIntersectionTestPredicate(), rayNodeIntersectionResult);
163  }
164 
165  template <typename TOutputIter>
166  inline TOutputIter GetLeafNodesIntersectingLineSegment(const Eegeo::Collision::CollisionBvh& collisionBvh,
167  const Eegeo::v3& lineSegmentStart,
168  const Eegeo::v3& lineSegmentDirection,
169  float lineSegmentLength,
170  TOutputIter rayNodeIntersectionResult)
171  {
172  const float skewedParamScale = 1.f;
173  BvhNodeLineSegmentIntersectionTest intersectionTest(collisionBvh, lineSegmentStart, lineSegmentDirection, lineSegmentLength, skewedParamScale);
174  WorkspaceStack workspaceStack;
175 
176  return GetCollisionBvhLeafNodes(workspaceStack, collisionBvh, intersectionTest, BvhNodeIntersectionTestPredicate(), rayNodeIntersectionResult);
177  }
178 
179  template <typename TOutputIter>
180  inline TOutputIter GetLeafNodesIntersectingSkewedRay(
181  const Eegeo::Collision::CollisionBvh& collisionBvh,
182  const SkewedRay& skewedRay,
183  TOutputIter rayNodeIntersectionResult)
184  {
185  BvhNodeRayIntersectionTest intersectionTest(collisionBvh, skewedRay.Origin, skewedRay.Direction, skewedRay.SkewedParamScale);
186  WorkspaceStack workspaceStack;
187 
188  return GetCollisionBvhLeafNodes(workspaceStack, collisionBvh, intersectionTest, BvhNodeIntersectionTestPredicate(), rayNodeIntersectionResult);
189  }
190 
191  template <typename TOutputIter>
192  TOutputIter GetLeafNodesIntersectingSkewedRayBruteForce(const Eegeo::Collision::CollisionBvh& collisionBvh,
193  const SkewedRay& skewedRay,
194  TOutputIter rayNodeIntersectionResult)
195  {
196  TOutputIter outIter = rayNodeIntersectionResult;
197  const std::vector<Eegeo::Collision::CollisionBvhNode>& nodes = collisionBvh.Nodes();
198  for (int i = 0; i < nodes.size(); ++i)
199  {
200  const Eegeo::Collision::CollisionBvhNode& node = nodes[i];
201  if (node.IsLeafNode())
202  {
203  float t;
204  const Geometry::SingleSphere& sphere = collisionBvh.GetSphere(node);
205  if ( Geometry::IntersectionTests::SphereIntersectsWithRay(sphere, skewedRay.Origin, skewedRay.Direction, t))
206  {
207  t *= skewedRay.SkewedParamScale;
208  *outIter++ = Eegeo::Collision::RayNodeIntersectionResult(skewedRay.Origin, skewedRay.Direction, skewedRay.SkewedParamScale, collisionBvh, node, true, t);
209  }
210  }
211  }
212  return outIter;
213  }
214 
215  template <typename TOutputIter>
216  TOutputIter GetTransformedLeafNodesIntersectingRay(
217  const Eegeo::Collision::CollisionBvh& collisionBvh,
218  const m44& inverseModelTransform,
219  const Eegeo::dv3& rayOriginEcef,
220  const Eegeo::dv3& rayDirectionEcef,
221  TOutputIter rayNodeIntersectionResults)
222  {
223  const SkewedRay& modelSpaceRay = CalculateModelSpaceRay(rayOriginEcef, rayDirectionEcef, collisionBvh.OriginEcef(), inverseModelTransform);
224 
225  return GetLeafNodesIntersectingSkewedRay(collisionBvh, modelSpaceRay, rayNodeIntersectionResults);
226  }
227 
228 
229  }
230 }