2
// ---------------------------------------------------------
7
// Tunicate-based implementation of collision and intersection queries. Uses exact arithmetic with SoS.
8
// (See Robert Bridson's "Tunicate" library.)
10
// ---------------------------------------------------------
12
#include <ccd_wrapper.h>
14
#ifdef USE_SOS_TUNICATE_CCD
20
const unsigned int nv = 1000000;
22
// return a unit-length vector orthogonal to u and v
23
static Vec3d get_normal(const Vec3d& u, const Vec3d& v)
28
// degenerate case: either u and v are parallel, or at least one is zero; pick an arbitrary orthogonal vector
30
if(std::fabs(u[0])>=std::fabs(u[1]) && std::fabs(u[0])>=std::fabs(u[2]))
31
c=Vec3d(-u[1]-u[2], u[0], u[0]);
32
else if(std::fabs(u[1])>=std::fabs(u[2]))
33
c=Vec3d(u[1], -u[0]-u[2], u[1]);
35
c=Vec3d(u[2], u[2], -u[0]-u[1]);
37
if(std::fabs(v[0])>=std::fabs(v[1]) && std::fabs(v[0])>=std::fabs(v[2]))
38
c=Vec3d(-v[1]-v[2], v[0], v[0]);
39
else if(std::fabs(v[1])>=std::fabs(v[2]))
40
c=Vec3d(v[1], -v[0]-v[2], v[1]);
42
c=Vec3d(v[2], v[2], -v[0]-v[1]);
46
// really degenerate case: u and v are both zero vectors; pick a random unit-length vector
47
c[0]=random()%2 ? -0.577350269189626 : 0.577350269189626;
48
c[1]=random()%2 ? -0.577350269189626 : 0.577350269189626;
49
c[2]=random()%2 ? -0.577350269189626 : 0.577350269189626;
53
// --------------------------------------------------------------------------------------------------------------
56
bool tunicate_point_triangle_collision(const Vec3d& x0, const Vec3d& xnew0, unsigned int index0,
57
const Vec3d& x1, const Vec3d& xnew1, unsigned int index1,
58
const Vec3d& x2, const Vec3d& xnew2, unsigned int index2,
59
const Vec3d& x3, const Vec3d& xnew3, unsigned int index3 )
62
const int segment_tetrahedron_test = 2;
64
double p0[4] = { x0[0], x0[1], x0[2], 0.0 };
65
double pnew0[4] = { xnew0[0], xnew0[1], xnew0[2], 1.0 };
66
double p1[4] = { x1[0], x1[1], x1[2], 0.0 };
67
double pnew1[4] = { xnew1[0], xnew1[1], xnew1[2], 1.0 };
68
double p2[4] = { x2[0], x2[1], x2[2], 0.0 };
69
double pnew2[4] = { xnew2[0], xnew2[1], xnew2[2], 1.0 };
70
double p3[4] = { x3[0], x3[1], x3[2], 0.0 };
71
double pnew3[4] = { xnew3[0], xnew3[1], xnew3[2], 1.0 };
73
double a0, a1, a2, a3, a4, a5;
75
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
82
&a0, &a1, &a2, &a3, &a4, &a5 ) )
87
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
94
&a0, &a1, &a2, &a3, &a4, &a5 ) )
99
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
106
&a0, &a1, &a2, &a3, &a4, &a5 ) )
115
// --------------------------------------------------------------------------------------------------------------
118
bool tunicate_point_triangle_collision(const Vec3d& x0, const Vec3d& xnew0, unsigned int index0,
119
const Vec3d& x1, const Vec3d& xnew1, unsigned int index1,
120
const Vec3d& x2, const Vec3d& xnew2, unsigned int index2,
121
const Vec3d& x3, const Vec3d& xnew3, unsigned int index3,
122
double& bary1, double& bary2, double& bary3,
125
double& relative_normal_displacement,
129
const int segment_tetrahedron_test = 2;
131
double p0[4] = { x0[0], x0[1], x0[2], 0.0 };
132
double pnew0[4] = { xnew0[0], xnew0[1], xnew0[2], 1.0 };
133
double p1[4] = { x1[0], x1[1], x1[2], 0.0 };
134
double pnew1[4] = { xnew1[0], xnew1[1], xnew1[2], 1.0 };
135
double p2[4] = { x2[0], x2[1], x2[2], 0.0 };
136
double pnew2[4] = { xnew2[0], xnew2[1], xnew2[2], 1.0 };
137
double p3[4] = { x3[0], x3[1], x3[2], 0.0 };
138
double pnew3[4] = { xnew3[0], xnew3[1], xnew3[2], 1.0 };
140
bool collision=false;
143
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
150
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
154
normal=get_normal(x2-x1, x3-x1);
155
relative_normal_displacement=dot(normal, (xnew0-x0)-(xnew3-x3));
158
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
165
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
167
if(!collision || bary[1]<t)
171
normal=get_normal(x2-x1, xnew3-xnew2);
172
relative_normal_displacement=dot(normal, (xnew0-x0)-(xnew2-x2));
176
if ( sos_simplex_intersection4d( segment_tetrahedron_test,
183
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
185
if(!collision || bary[1]<t)
189
normal=get_normal(xnew2-xnew1, xnew3-xnew1);
190
relative_normal_displacement=dot(normal, (xnew0-x0)-(xnew1-x1));
198
// --------------------------------------------------------------------------------------------------------------
201
bool tunicate_segment_segment_collision(const Vec3d& x0, const Vec3d& xnew0, unsigned int index0,
202
const Vec3d& x1, const Vec3d& xnew1, unsigned int index1,
203
const Vec3d& x2, const Vec3d& xnew2, unsigned int index2,
204
const Vec3d& x3, const Vec3d& xnew3, unsigned int index3)
207
const int triangle_triangle_test = 3;
209
double p0[4] = { x0[0], x0[1], x0[2], 0.0 };
210
double pnew0[4] = { xnew0[0], xnew0[1], xnew0[2], 1.0 };
211
double p1[4] = { x1[0], x1[1], x1[2], 0.0 };
212
double pnew1[4] = { xnew1[0], xnew1[1], xnew1[2], 1.0 };
213
double p2[4] = { x2[0], x2[1], x2[2], 0.0 };
214
double pnew2[4] = { xnew2[0], xnew2[1], xnew2[2], 1.0 };
215
double p3[4] = { x3[0], x3[1], x3[2], 0.0 };
216
double pnew3[4] = { xnew3[0], xnew3[1], xnew3[2], 1.0 };
220
if ( sos_simplex_intersection4d( triangle_triangle_test,
227
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
232
if ( sos_simplex_intersection4d( triangle_triangle_test,
239
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
244
if ( sos_simplex_intersection4d( triangle_triangle_test,
251
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
256
if ( sos_simplex_intersection4d( triangle_triangle_test,
263
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
272
// --------------------------------------------------------------------------------------------------------------
276
bool tunicate_segment_segment_collision(const Vec3d& x0, const Vec3d& xnew0, unsigned int index0,
277
const Vec3d& x1, const Vec3d& xnew1, unsigned int index1,
278
const Vec3d& x2, const Vec3d& xnew2, unsigned int index2,
279
const Vec3d& x3, const Vec3d& xnew3, unsigned int index3,
280
double& bary0, double& bary2,
283
double& relative_normal_displacement,
287
const int triangle_triangle_test = 3;
289
double p0[4] = { x0[0], x0[1], x0[2], 0.0 };
290
double pnew0[4] = { xnew0[0], xnew0[1], xnew0[2], 1.0 };
291
double p1[4] = { x1[0], x1[1], x1[2], 0.0 };
292
double pnew1[4] = { xnew1[0], xnew1[1], xnew1[2], 1.0 };
293
double p2[4] = { x2[0], x2[1], x2[2], 0.0 };
294
double pnew2[4] = { xnew2[0], xnew2[1], xnew2[2], 1.0 };
295
double p3[4] = { x3[0], x3[1], x3[2], 0.0 };
296
double pnew3[4] = { xnew3[0], xnew3[1], xnew3[2], 1.0 };
298
bool collision=false;
301
if ( sos_simplex_intersection4d( triangle_triangle_test,
308
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
314
normal=get_normal(x1-x0, x3-x2);
315
relative_normal_displacement=dot(normal, (xnew1-x1)-(xnew3-x3));
318
if ( sos_simplex_intersection4d( triangle_triangle_test,
325
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
327
if(!collision || bary[5]<t)
330
bary0=0.5;//(bary[1]+1e-300)/(bary[1]+bary[2]+2e-300); // guard against zero/zero
333
normal=get_normal(xnew1-xnew0, x3-x2);
334
relative_normal_displacement=dot(normal, (xnew0-x0)-(xnew3-x3));
338
if ( sos_simplex_intersection4d( triangle_triangle_test,
345
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
347
if(!collision || bary[2]<t){
350
bary2=0.5;//(bary[4]+1e-300)/(bary[4]+bary[5]+2e-300); // guard against zero/zero
352
normal=get_normal(x1-x0, xnew3-xnew2);
353
relative_normal_displacement=dot(normal, (xnew1-x1)-(xnew2-x2));
357
if ( sos_simplex_intersection4d( triangle_triangle_test,
364
&bary[0], &bary[1], &bary[2], &bary[3], &bary[4], &bary[5] ) )
366
if(!collision || 1-bary[0]<t){
368
bary0=0.5;//(bary[1]+1e-300)/(bary[1]+bary[2]+2e-300); // guard against zero/zero
369
bary2=0.5;//(bary[4]+1e-300)/(bary[4]+bary[5]+2e-300); // guard against zero/zero
371
normal=get_normal(xnew1-xnew0, xnew3-xnew2);
372
relative_normal_displacement=dot(normal, (xnew0-x0)-(xnew2-x2));