PeriDyno 1.0.0
Loading...
Searching...
No Matches
TightCCD.inl
Go to the documentation of this file.
1#include "Vector.h"
2
3namespace dyno
4{
5 #define REAL_infinity 1.0e30
6 #define REAL_EQUAL(a,b) (((a < b + EPSILON) && (a > b - EPSILON)) ? true : false)
7
8
9 template<typename T>
10 inline DYN_FUNC T STP(
11 const Vector<T, 3>& u, const Vector<T, 3>& v, const Vector<T, 3>& w)
12 {
13 return u.dot(v.cross(w));
14 }
15
16 template<typename T>
17 inline DYN_FUNC void fswap(T& a, T& b)
18 {
19 T t = b;
20 b = a;
21 a = t;
22 }
23
24 template<typename T>
26 const Vector<T, 3>& x,
27 const Vector<T, 3>& y0,
28 const Vector<T, 3>& y1,
29 const Vector<T, 3>& y2,
30 Vector<T, 3>* n,
31 T* w)
32 {
33 Vector<T, 3> _n; if (!n) n = &_n;
34 T _w[4]; if (!w) w = _w;
35 Vector<T, 3> y01 = y1 - y0; y01.normalize();
36 Vector<T, 3> y02 = y2 - y0; y02.normalize();
37
38 *n = y01.cross(y02);
39 if ((*n).normSquared() < 1e-6)
40 return REAL_infinity;
41 *n = (*n).normalize();
42 T h = (x - y0).dot(*n);
43 T b0 = STP(y1 - x, y2 - x, *n),
44 b1 = STP(y2 - x, y0 - x, *n),
45 b2 = STP(y0 - x, y1 - x, *n);
46 w[0] = 1;
47 w[1] = -b0 / (b0 + b1 + b2);
48 w[2] = -b1 / (b0 + b1 + b2);
49 w[3] = -b2 / (b0 + b1 + b2);
50 return h;
51 }
52
53 template<typename T>
55 const Vector<T, 3>& x0, const Vector<T, 3>& x1,
56 const Vector<T, 3>& y0, const Vector<T, 3>& y1,
57 Vector<T, 3>* n,
58 Real* w)
59 {
60 Vector<T, 3> _n; if (!n) n = &_n;
61 T _w[4]; if (!w) w = _w;
62
63 Vector<T, 3> x01 = (x1 - x0); x01.normalize();
64 Vector<T, 3> y01 = (y1 - y0); y01.normalize();
65
66 *n = x01.cross(y01);
67 if ((*n).normSquared() < 1e-6)
68 return REAL_infinity;
69
70 *n = (*n).normalize();
71 T h = (x0 - y0).dot(*n);
72 T a0 = STP(y1 - x1, y0 - x1, *n);
73 T a1 = STP(y0 - x0, y1 - x0, *n);
74 T b0 = STP(x0 - y1, x1 - y1, *n);
75 T b1 = STP(x1 - y0, x0 - y0, *n);
76 w[0] = a0 / (a0 + a1);
77 w[1] = a1 / (a0 + a1);
78 w[2] = -b0 / (b0 + b1);
79 w[3] = -b1 / (b0 + b1);
80 return h;
81 }
82
83 template<typename T>
85 {
86 return a.cross(b).dot(c);
87 }
88
89 template<typename T>
91 {
92 return x + v * t;
93 }
94
95 template<typename T>
96 DYN_FUNC int sgn(T x) { return x < 0 ? -1 : 1; }
97
98 template<typename T>
99 inline DYN_FUNC int SolveQuadratic(T a, T b, T c, T x[2]) {
100 // http://en.wikipedia.org/wiki/Quadratic_formula#Floating_point_implementation
101 T d = b * b - 4 * a * c;
102 if (d < 0) {
103 x[0] = -b / (2 * a);
104 return 0;
105 }
106 T q = -(b + sgn(b) * glm::sqrt(d)) / 2;
107 int i = 0;
108 if (glm::abs(a) > 1e-12 * glm::abs(q))
109 x[i++] = q / a;
110 if (glm::abs(q) > 1e-12 * glm::abs(c))
111 x[i++] = c / q;
112 if (i == 2 && x[0] > x[1])
113 fswap(x[0], x[1]);
114 return i;
115 }
116
117 template<typename T>
118 inline DYN_FUNC T NewtonsMethod(T a, T b, T c, T d, T x0, int init_dir)
119 {
120 if (init_dir != 0) {
121 // quadratic approximation around x0, assuming y' = 0
122 T y0 = d + x0 * (c + x0 * (b + x0 * a)),
123 ddy0 = 2 * b + x0 * (6 * a);
124 x0 += init_dir * glm::sqrt(glm::abs(2 * y0 / ddy0));
125 }
126 for (int iter = 0; iter < 100; iter++) {
127 T y = d + x0 * (c + x0 * (b + x0 * a));
128 T dy = c + x0 * (2 * b + x0 * 3 * a);
129 if (dy == 0)
130 return x0;
131 T x1 = x0 - y / dy;
132 if (glm::abs(x0 - x1) < 1e-6)
133 return x0;
134 x0 = x1;
135 }
136 return x0;
137 }
138
139 // solves a x^3 + b x^2 + c x + d == 0
140 template<typename T>
141 inline DYN_FUNC int SolveCubic(T a, T b, T c, T d, T x[3])
142 {
143 T xc[2];
144 int ncrit = SolveQuadratic(3 * a, 2 * b, c, xc);
145 if (ncrit == 0) {
146 x[0] = NewtonsMethod(a, b, c, d, xc[0], 0);
147 return 1;
148 }
149 else if (ncrit == 1) {// cubic is actually quadratic
150 return SolveQuadratic(b, c, d, x);
151 }
152 else {
153 T yc[2] = { d + xc[0] * (c + xc[0] * (b + xc[0] * a)),
154 d + xc[1] * (c + xc[1] * (b + xc[1] * a)) };
155 int i = 0;
156 if (yc[0] * a >= 0)
157 x[i++] = NewtonsMethod(a, b, c, d, xc[0], -1);
158 if (yc[0] * yc[1] <= 0) {
159 int closer = abs(yc[0]) < abs(yc[1]) ? 0 : 1;
160 x[i++] = NewtonsMethod(a, b, c, d, xc[closer], closer == 0 ? 1 : -1);
161 }
162 if (yc[1] * a <= 0)
163 x[i++] = NewtonsMethod(a, b, c, d, xc[1], 1);
164 return i;
165 }
166 }
167
168 template<typename T>
169 DYN_FUNC bool CollisionTest(
170 const Vector<T, 3>& x0, const Vector<T, 3>& x1, const Vector<T, 3>& x2, const Vector<T, 3>& x3,
171 const Vector<T, 3>& v0, const Vector<T, 3>& v1, const Vector<T, 3>& v2, const Vector<T, 3>& v3,
172 T& time, const int isVF)//0:vf 1:ee
173 {
174 T a0 = STP(x1, x2, x3);
175 T a1 = STP(v1, x2, x3) + STP(x1, v2, x3) + STP(x1, x2, v3);
176 T a2 = STP(x1, v2, v3) + STP(v1, x2, v3) + STP(v1, v2, x3);
177 T a3 = STP(v1, v2, v3);
178
179 if (REAL_EQUAL(a1, 0) && REAL_EQUAL(a2, 0) && REAL_EQUAL(a1, 0))
180 //if (a1 == 0 && a2 == 0 && a3 == 0)
181 return false;
182
183 T t[4];
184 int nsol = SolveCubic(a3, a2, a1, a0, t);
185 //t[nsol] = 1; // also check at end of timestep
186
187 bool t_flag = false;
188 for (int i = 0; i < nsol; i++) {
189 if (t[i] < 0 || t[i] > 1)
190 continue;
191
192 Vector<T, 3> tx0 = xvpos(x0, v0, t[i]);
193 Vector<T, 3> tx1 = xvpos(x1 + x0, v1 + v0, t[i]);
194 Vector<T, 3> tx2 = xvpos(x2 + x0, v2 + v0, t[i]);
195 Vector<T, 3> tx3 = xvpos(x3 + x0, v3 + v0, t[i]);
196
197 Vector<T, 3> n;
198 T w[4];
199 T d;
200 bool inside;
201
202 if (isVF == 0) {
203 d = SignedDistanceVF(tx0, tx1, tx2, tx3, &n, w);
204 inside = (fmin(-w[1], fmin(-w[2], -w[3])) >= -1e-6);
205 }
206 else {// Impact::EE
207 d = SignedDistanceEE(tx0, tx1, tx2, tx3, &n, w);
208 inside = (fmin(fmin(w[0], w[1]), fmin(-w[2], -w[3])) >= -1e-6);
209 }
210
211 if (fabs(d) < 1e-6 && inside)
212 {
213// time = t[i];
214// return true;
215 time = t[i] < time ? t[i] : time;
216 t_flag = true;
217 }
218 }
219 return t_flag;
220 }
221
222 template<typename T>
224 const Vector<T, 3>& p0, const Vector<T, 3>& a0, const Vector<T, 3>& b0, const Vector<T, 3>& c0,
225 const Vector<T, 3>& p1, const Vector<T, 3>& a1, const Vector<T, 3>& b1, const Vector<T, 3>& c1,
226 T& time)
227 {
228 Vector<T, 3> x0 = p0;
229 Vector<T, 3> x1 = a0 - p0;
230 Vector<T, 3> x2 = b0 - p0;
231 Vector<T, 3> x3 = c0 - p0;
232 Vector<T, 3> v0 = p1 - p0;
233 Vector<T, 3> v1 = a1 - a0 - v0;
234 Vector<T, 3> v2 = b1 - b0 - v0;
235 Vector<T, 3> v3 = c1 - c0 - v0;
236
237 return CollisionTest(x0, x1, x2, x3, v0, v1, v2, v3, time, 0);
238 }
239
240 template<typename T>
242 const Vector<T, 3>& a0, const Vector<T, 3>& b0, const Vector<T, 3>& c0, const Vector<T, 3>& d0,
243 const Vector<T, 3>& a1, const Vector<T, 3>& b1, const Vector<T, 3>& c1, const Vector<T, 3>& d1,
244 T& time)
245 {
246 Vector<T, 3> p0 = a0;
247 Vector<T, 3> p1 = b0 - a0;
248 Vector<T, 3> p2 = c0 - a0;
249 Vector<T, 3> p3 = d0 - a0;
250 Vector<T, 3> v0 = a1 - a0;
251 Vector<T, 3> v1 = b1 - b0 - v0;
252 Vector<T, 3> v2 = c1 - c0 - v0;
253 Vector<T, 3> v3 = d1 - d0 - v0;
254
255 return CollisionTest(a0, p1, p2, p3, v0, v1, v2, v3, time, 1);
256 }
257
258 template<typename T>
260 {
261 Real l0 = s0.maximumEdgeLength();
262 Real l1 = s1.maximumEdgeLength();
263 Real l2 = t0.maximumEdgeLength();
264 Real l3 = t1.maximumEdgeLength();
265
266 Real lmax = maximum(maximum(l0, l1), maximum(l2, l3));
267 if (lmax < REAL_EPSILON)
268 return false;
269
270 Real invL = 1 / lmax;
271
272 Vector<Real, 3> p[3];
273 p[0] = invL * s0.v[0];
274 p[1] = invL * s0.v[1];
275 p[2] = invL * s0.v[2];
276
277 Vector<Real, 3> pp[3];
278 pp[0] = invL * s1.v[0];
279 pp[1] = invL * s1.v[1];
280 pp[2] = invL * s1.v[2];
281
282 Vector<Real, 3> q[3];
283 q[0] = invL * t0.v[0];
284 q[1] = invL * t0.v[1];
285 q[2] = invL * t0.v[2];
286
287 Vector<Real, 3> qq[3];
288 qq[0] = invL * t1.v[0];
289 qq[1] = invL * t1.v[1];
290 qq[2] = invL * t1.v[2];
291
293 //VF
294 bool ret = false;
295 for (int st = 0; st < 3; st++)
296 {
297 Real t = Real(1);
298 bool collided = VertexFaceCCD(
299 p[st], q[0], q[1], q[2],
300 pp[st], qq[0], qq[1], qq[2],
301 t);
302
303 toi = collided ? minimum(t, toi) : toi;
304 ret |= collided;
305 }
306
307 //VF
308 for (int st = 0; st < 3; st++)
309 {
310 Real t = Real(1);
311 bool collided = VertexFaceCCD(q[st], p[0], p[1], p[2],
312 qq[st], pp[0], pp[1], pp[2],
313 t);
314 toi = collided ? minimum(t, toi) : toi;
315 ret |= collided;
316 }
317
318 //EE
319 for (int st = 0; st < 3; st++)
320 {
321 int ind0 = st;
322 int ind1 = (st + 1) % 3;
323 for (int ss = 0; ss < 3; ss++)
324 {
325 int ind2 = ss;
326 int ind3 = (ss + 1) % 3;
327
328 Real t = Real(1);
329 bool collided = EdgeEdgeCCD(
330 p[ind0], p[ind1], q[ind2], q[ind3],
331 pp[ind0], pp[ind1], qq[ind2], qq[ind3],
332 t);
333
334 toi = collided ? minimum(t, toi) : toi;
335 ret |= collided;
336 }
337 }
338
339 return ret;
340 }
341}
#define REAL_infinity
#define REAL_EQUAL(a, b)
double Real
Definition Typedef.inl:23
DYN_FUNC Real maximumEdgeLength() const
static DYN_FUNC bool EdgeEdgeCCD(const Vector< T, 3 > &a0, const Vector< T, 3 > &b0, const Vector< T, 3 > &c0, const Vector< T, 3 > &d0, const Vector< T, 3 > &a1, const Vector< T, 3 > &b1, const Vector< T, 3 > &c1, const Vector< T, 3 > &d1, T &time)
Do a continuous collision detection between two edges.
Definition TightCCD.inl:241
static DYN_FUNC bool VertexFaceCCD(const Vector< T, 3 > &p0, const Vector< T, 3 > &a0, const Vector< T, 3 > &b0, const Vector< T, 3 > &c0, const Vector< T, 3 > &p1, const Vector< T, 3 > &a1, const Vector< T, 3 > &b1, const Vector< T, 3 > &c1, T &time)
Do a continuous collision detection between a vertex and a triangle.
Definition TightCCD.inl:223
static DYN_FUNC bool TriangleCCD(TTriangle3D< Real > &s0, TTriangle3D< Real > &s1, TTriangle3D< Real > &t0, TTriangle3D< Real > &t1, Real &toi)
Do a continuous collision detection between two triangles.
Definition TightCCD.inl:259
#define T(t)
This is an implementation of AdditiveCCD based on peridyno.
Definition Array.h:25
DYN_FUNC Vector< T, 3 > xvpos(Vector< T, 3 > x, Vector< T, 3 > v, T t)
Definition TightCCD.inl:90
DYN_FUNC T dot(Vector< T, 2 > const &U, Vector< T, 2 > const &V)
Definition SimpleMath.h:199
DYN_FUNC T abs(const T &v)
Definition SimpleMath.h:81
DYN_FUNC T SignedDistanceVF(const Vector< T, 3 > &x, const Vector< T, 3 > &y0, const Vector< T, 3 > &y1, const Vector< T, 3 > &y2, Vector< T, 3 > *n, T *w)
Definition TightCCD.inl:25
DYN_FUNC T triProduct(Vector< T, 3 > &a, Vector< T, 3 > &b, Vector< T, 3 > &c)
Definition TightCCD.inl:84
DYN_FUNC int SolveQuadratic(T a, T b, T c, T x[2])
Definition TightCCD.inl:99
DYN_FUNC T minimum(const T &v0, const T &v1)
Definition SimpleMath.h:120
DYN_FUNC int SolveCubic(T a, T b, T c, T d, T x[3])
Definition TightCCD.inl:141
constexpr Real REAL_EPSILON
Definition Typedef.inl:43
DYN_FUNC T SignedDistanceEE(const Vector< T, 3 > &x0, const Vector< T, 3 > &x1, const Vector< T, 3 > &y0, const Vector< T, 3 > &y1, Vector< T, 3 > *n, Real *w)
Definition TightCCD.inl:54
DYN_FUNC T STP(const Vector< T, 3 > &u, const Vector< T, 3 > &v, const Vector< T, 3 > &w)
Definition TightCCD.inl:10
DYN_FUNC void fswap(T &a, T &b)
Definition TightCCD.inl:17
DYN_FUNC T NewtonsMethod(T a, T b, T c, T d, T x0, int init_dir)
Definition TightCCD.inl:118
DYN_FUNC T maximum(const T &v0, const T &v1)
Definition SimpleMath.h:160
DYN_FUNC bool CollisionTest(const Vector< T, 3 > &x0, const Vector< T, 3 > &x1, const Vector< T, 3 > &x2, const Vector< T, 3 > &x3, const Vector< T, 3 > &v0, const Vector< T, 3 > &v1, const Vector< T, 3 > &v2, const Vector< T, 3 > &v3, T &time, const int isVF)
Definition TightCCD.inl:169
DYN_FUNC int sgn(T x)
Definition TightCCD.inl:96