GteIntrRay3Triangle3.h
Go to the documentation of this file.
1 // David Eberly, Geometric Tools, Redmond WA 98052
2 // Copyright (c) 1998-2017
3 // Distributed under the Boost Software License, Version 1.0.
4 // http://www.boost.org/LICENSE_1_0.txt
5 // http://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
6 // File Version: 3.0.0 (2016/06/19)
7 
8 #pragma once
9 
10 #include <Mathematics/GteVector3.h>
11 #include <Mathematics/GteRay.h>
13 #include <Mathematics/GteFIQuery.h>
14 #include <Mathematics/GteTIQuery.h>
15 
16 namespace gte
17 {
18 
19 template <typename Real>
20 class TIQuery<Real, Ray3<Real>, Triangle3<Real>>
21 {
22 public:
23  struct Result
24  {
25  bool intersect;
26  };
27 
28  Result operator()(Ray3<Real> const& ray, Triangle3<Real> const& triangle);
29 };
30 
31 template <typename Real>
32 class FIQuery<Real, Ray3<Real>, Triangle3<Real>>
33 {
34 public:
35  struct Result
36  {
37  Result();
38 
39  bool intersect;
40  Real parameter;
41  Real triangleBary[3];
43  };
44 
45  Result operator()(Ray3<Real> const& ray, Triangle3<Real> const& triangle);
46 };
47 
48 
49 template <typename Real>
52  Ray3<Real> const& ray, Triangle3<Real> const& triangle)
53 {
54  Result result;
55 
56  // Compute the offset origin, edges, and normal.
57  Vector3<Real> diff = ray.origin - triangle.v[0];
58  Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
59  Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
60  Vector3<Real> normal = Cross(edge1, edge2);
61 
62  // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
63  // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
64  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
65  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
66  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
67  Real DdN = Dot(ray.direction, normal);
68  Real sign;
69  if (DdN > (Real)0)
70  {
71  sign = (Real)1;
72  }
73  else if (DdN < (Real)0)
74  {
75  sign = (Real)-1;
76  DdN = -DdN;
77  }
78  else
79  {
80  // Ray and triangle are parallel, call it a "no intersection"
81  // even if the ray does intersect.
82  result.intersect = false;
83  return result;
84  }
85 
86  Real DdQxE2 = sign*DotCross(ray.direction, diff, edge2);
87  if (DdQxE2 >= (Real)0)
88  {
89  Real DdE1xQ = sign*DotCross(ray.direction, edge1, diff);
90  if (DdE1xQ >= (Real)0)
91  {
92  if (DdQxE2 + DdE1xQ <= DdN)
93  {
94  // Line intersects triangle, check whether ray does.
95  Real QdN = -sign*Dot(diff, normal);
96  if (QdN >= (Real)0)
97  {
98  // Ray intersects triangle.
99  result.intersect = true;
100  return result;
101  }
102  // else: t < 0, no intersection
103  }
104  // else: b1+b2 > 1, no intersection
105  }
106  // else: b2 < 0, no intersection
107  }
108  // else: b1 < 0, no intersection
109 
110  result.intersect = false;
111  return result;
112 }
113 
114 template <typename Real>
116  :
117  parameter((Real)0)
118 {
119  triangleBary[0] = (Real)0;
120  triangleBary[1] = (Real)0;
121  triangleBary[2] = (Real)0;
122 }
123 
124 template <typename Real>
125 typename FIQuery<Real, Ray3<Real>, Triangle3<Real>>::Result
127  Ray3<Real> const& ray, Triangle3<Real> const& triangle)
128 {
129  Result result;
130 
131  // Compute the offset origin, edges, and normal.
132  Vector3<Real> diff = ray.origin - triangle.v[0];
133  Vector3<Real> edge1 = triangle.v[1] - triangle.v[0];
134  Vector3<Real> edge2 = triangle.v[2] - triangle.v[0];
135  Vector3<Real> normal = Cross(edge1, edge2);
136 
137  // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction,
138  // E1 = edge1, E2 = edge2, N = Cross(E1,E2)) by
139  // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2))
140  // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q))
141  // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N)
142  Real DdN = Dot(ray.direction, normal);
143  Real sign;
144  if (DdN > (Real)0)
145  {
146  sign = (Real)1;
147  }
148  else if (DdN < (Real)0)
149  {
150  sign = (Real)-1;
151  DdN = -DdN;
152  }
153  else
154  {
155  // Ray and triangle are parallel, call it a "no intersection"
156  // even if the ray does intersect.
157  result.intersect = false;
158  return result;
159  }
160 
161  Real DdQxE2 = sign*DotCross(ray.direction, diff, edge2);
162  if (DdQxE2 >= (Real)0)
163  {
164  Real DdE1xQ = sign*DotCross(ray.direction, edge1, diff);
165  if (DdE1xQ >= (Real)0)
166  {
167  if (DdQxE2 + DdE1xQ <= DdN)
168  {
169  // Line intersects triangle, check whether ray does.
170  Real QdN = -sign*Dot(diff, normal);
171  if (QdN >= (Real)0)
172  {
173  // Ray intersects triangle.
174  result.intersect = true;
175  Real inv = ((Real)1) / DdN;
176  result.parameter = QdN*inv;
177  result.triangleBary[1] = DdQxE2*inv;
178  result.triangleBary[2] = DdE1xQ*inv;
179  result.triangleBary[0] = (Real)1 - result.triangleBary[1]
180  - result.triangleBary[2];
181  result.point = ray.origin +
182  result.parameter * ray.direction;
183  return result;
184  }
185  // else: t < 0, no intersection
186  }
187  // else: b1+b2 > 1, no intersection
188  }
189  // else: b2 < 0, no intersection
190  }
191  // else: b1 < 0, no intersection
192 
193  result.intersect = false;
194  return result;
195 }
196 
197 
198 }
DualQuaternion< Real > Dot(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
DualQuaternion< Real > Cross(DualQuaternion< Real > const &d0, DualQuaternion< Real > const &d1)
Real DotCross(Vector< N, Real > const &v0, Vector< N, Real > const &v1, Vector< N, Real > const &v2)
Definition: GteVector3.h:140
Result operator()(Type0 const &primitive0, Type1 const &primitive1)
GLuint64EXT * result
Definition: glext.h:10003


geometric_tools_engine
Author(s): Yijiang Huang
autogenerated on Thu Jul 18 2019 04:00:00