DART 6.12.2
Loading...
Searching...
No Matches
tri_tri_intersection_test.hpp
Go to the documentation of this file.
1/*
2 * Copyright (c) 2011-2021, The DART development contributors
3 * All rights reserved.
4 *
5 * The list of contributors can be found at:
6 * https://github.com/dartsim/dart/blob/master/LICENSE
7 *
8 * This file is provided under the following "BSD-style" License:
9 * Redistribution and use in source and binary forms, with or
10 * without modification, are permitted provided that the following
11 * conditions are met:
12 * * Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * * Redistributions in binary form must reproduce the above
15 * copyright notice, this list of conditions and the following
16 * disclaimer in the documentation and/or other materials provided
17 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
26 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30 * POSSIBILITY OF SUCH DAMAGE.
31 */
32
33#ifndef DART_COLLISION_TRITRIINTERSECTIONTEST_HPP_
34#define DART_COLLISION_TRITRIINTERSECTIONTEST_HPP_
35
36#include <cmath>
37
38/* some macros */
39#define DART_CROSS(dest, v1, v2) \
40 dest[0] = v1[1] * v2[2] - v1[2] * v2[1]; \
41 dest[1] = v1[2] * v2[0] - v1[0] * v2[2]; \
42 dest[2] = v1[0] * v2[1] - v1[1] * v2[0];
43
44#define DART_DOT(v1, v2) (v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2])
45
46#define DART_SUB(dest, v1, v2) \
47 dest[0] = v1[0] - v2[0]; \
48 dest[1] = v1[1] - v2[1]; \
49 dest[2] = v1[2] - v2[2];
50
51#define DART_ADD(dest, v1, v2) \
52 dest[0] = v1[0] + v2[0]; \
53 dest[1] = v1[1] + v2[1]; \
54 dest[2] = v1[2] + v2[2];
55
56#define DART_MULT(dest, v, factor) \
57 dest[0] = factor * v[0]; \
58 dest[1] = factor * v[1]; \
59 dest[2] = factor * v[2];
60
61#define DART_DIV(dest, v1, v2) \
62 dest[0] = v1[0] / v2[0]; \
63 dest[1] = v1[1] / 2 [1]; \
64 dest[2] = v1[2] / v2[2];
65
66#define DART_SET(dest, src) \
67 dest[0] = src[0]; \
68 dest[1] = src[1]; \
69 dest[2] = src[2];
70
71/* sort so that a<=b */
72#define DART_SORT(a, b) \
73 if (a > b) \
74 { \
75 float c; \
76 c = a; \
77 a = b; \
78 b = c; \
79 }
80
81#define DART_SWAP(a, b) \
82 { \
83 float c; \
84 c = a; \
85 a = b; \
86 b = c; \
87 }
88
89#define DART_ISECT(VV0, VV1, VV2, D0, D1, D2, isect0, isect1) \
90 isect0 = VV0 + (VV1 - VV0) * D0 / (D0 - D1); \
91 isect1 = VV0 + (VV2 - VV0) * D0 / (D0 - D2);
92
93#define DART_COMPUTE_INTERVALS( \
94 VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, isect0, isect1) \
95 if (D0D1 > 0.0f) \
96 { \
97 /* here we know that D0D2<=0.0 */ \
98 /* that is D0, D1 are on the same side, D2 on the other or on the plane */ \
99 DART_ISECT(VV2, VV0, VV1, D2, D0, D1, isect0, isect1); \
100 } \
101 else if (D0D2 > 0.0f) \
102 { \
103 /* here we know that d0d1<=0.0 */ \
104 DART_ISECT(VV1, VV0, VV2, D1, D0, D2, isect0, isect1); \
105 } \
106 else if (D1 * D2 > 0.0f || D0 != 0.0f) \
107 { \
108 /* here we know that d0d1<=0.0 or that D0!=0.0 */ \
109 DART_ISECT(VV0, VV1, VV2, D0, D1, D2, isect0, isect1); \
110 } \
111 else if (D1 != 0.0f) \
112 { \
113 DART_ISECT(VV1, VV0, VV2, D1, D0, D2, isect0, isect1); \
114 } \
115 else if (D2 != 0.0f) \
116 { \
117 DART_ISECT(VV2, VV0, VV1, D2, D0, D1, isect0, isect1); \
118 } \
119 else \
120 { \
121 /* triangles are coplanar */ \
122 return COPLANAR_CONTACT; \
123 }
124
125namespace dart {
126namespace collision {
127
128/* if USE_EPSILON_TEST is true then we do a check:
129 if |dv|<EPSILON then dv=0.0;
130 else no check is done (which is less robust)
131*/
132constexpr bool USE_EPSILON_TEST = true;
133constexpr double EPSILON = 1e-6;
134
135constexpr int NO_CONTACT = 0;
136constexpr int COPLANAR_CONTACT = -1;
137constexpr int INTERIAL_CONTACT = 1;
138
139/* implement as is fastest on your machine */
140inline float FABS(float x)
141{
142 return ((float)fabs(x));
143}
144
146 float V0[3], float V1[3], float DV0, float DV1, float V[3])
147{
148 float VV0[3], VV1[3];
149 DART_MULT(VV0, V1, DV0);
150 DART_MULT(VV1, V0, DV1);
151 float U[3], D;
152 DART_SUB(U, VV0, VV1);
153 D = DV0 - DV1;
154 DART_MULT(V, U, 1.0 / D);
155}
156
158 float V0[3],
159 float V1[3],
160 float V2[3],
161 float U0[3],
162 float U1[3],
163 float U2[3],
164 float res1[3],
165 float res2[3])
166{
167 float E1[3], E2[3];
168 float N1[3], N2[3], d1, d2;
169 float du0, du1, du2, dv0, dv1, dv2;
170 float D[3];
171 float isect1[2], isect2[2];
172 float du0du1, du0du2, dv0dv1, dv0dv2, du1du2, dv1dv2;
173 short index;
174 float vp0, vp1, vp2;
175 float up0, up1, up2;
176 float b, c, max;
177
178 /* compute plane equation of triangle(V0,V1,V2) */
179 DART_SUB(E1, V1, V0);
180 DART_SUB(E2, V2, V0);
181 DART_CROSS(N1, E1, E2);
182 d1 = -DART_DOT(N1, V0);
183 /* plane equation 1: N1.X+d1=0 */
184
185 /* put U0,U1,U2 into plane equation 1 to compute signed distances to the
186 * plane*/
187 du0 = DART_DOT(N1, U0) + d1;
188 du1 = DART_DOT(N1, U1) + d1;
189 du2 = DART_DOT(N1, U2) + d1;
190
191 /* coplanarity robustness check */
192#if USE_EPSILON_TEST == TRUE
193 if (fabs(du0) < EPSILON)
194 du0 = 0.0;
195 if (fabs(du1) < EPSILON)
196 du1 = 0.0;
197 if (fabs(du2) < EPSILON)
198 du2 = 0.0;
199 if (du1 == 0 && du2 == 0 && fabs(du0) < 1e-4)
200 du0 = 0.0;
201 if (du0 == 0 && du2 == 0 && fabs(du1) < 1e-4)
202 du1 = 0.0;
203 if (du0 == 0 && du1 == 0 && fabs(du2) < 1e-4)
204 du2 = 0.0;
205#endif
206 du0du1 = du0 * du1;
207 du0du2 = du0 * du2;
208 du1du2 = du1 * du2;
209
210 if (du0du1 > 0.0f && du0du2 > 0.0f)
211 { /* same sign on all of them + not equal 0 ? */
212 return NO_CONTACT; /* no intersection occurs */
213 }
214 /* compute plane of triangle (U0,U1,U2) */
215 DART_SUB(E1, U1, U0);
216 DART_SUB(E2, U2, U0);
217 DART_CROSS(N2, E1, E2);
218 d2 = -DART_DOT(N2, U0);
219 /* plane equation 2: N2.X+d2=0 */
220
221 /* put V0,V1,V2 into plane equation 2 */
222 dv0 = DART_DOT(N2, V0) + d2;
223 dv1 = DART_DOT(N2, V1) + d2;
224 dv2 = DART_DOT(N2, V2) + d2;
225
226#if USE_EPSILON_TEST == TRUE
227 if (fabs(dv0) < EPSILON)
228 dv0 = 0.0;
229 if (fabs(dv1) < EPSILON)
230 dv1 = 0.0;
231 if (fabs(dv2) < EPSILON)
232 dv2 = 0.0;
233 if (dv1 == 0 && dv2 == 0 && fabs(dv0) < 1e-5)
234 dv0 = 0.0;
235 if (dv0 == 0 && dv2 == 0 && fabs(dv1) < 1e-5)
236 dv1 = 0.0;
237 if (dv0 == 0 && dv1 == 0 && fabs(dv2) < 1e-5)
238 dv2 = 0.0;
239#endif
240 dv0dv1 = dv0 * dv1;
241 dv0dv2 = dv0 * dv2;
242 dv1dv2 = dv1 * dv2;
243
244 if (dv0dv1 > 0.0f && dv0dv2 > 0.0f)
245 { /* same sign on all of them + not equal 0 ? */
246 return NO_CONTACT; /* no intersection occurs */
247 }
248 /* compute direction of intersection line */
249 DART_CROSS(D, N1, N2);
250
251 /* compute and index to the largest component of D */
252 max = fabs(D[0]);
253 index = 0;
254 b = fabs(D[1]);
255 c = fabs(D[2]);
256 if (b > max)
257 max = b, index = 1;
258 if (c > max)
259 max = c, index = 2;
260
261 /* this is the simplified projection onto L*/
262 vp0 = V0[index];
263 vp1 = V1[index];
264 vp2 = V2[index];
265
266 up0 = U0[index];
267 up1 = U1[index];
268 up2 = U2[index];
269
270 /* compute interval for triangle 1 */
272 vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, isect1[0], isect1[1]);
273
274 /* compute interval for triangle 2 */
276 up0, up1, up2, du0, du1, du2, du0du1, du0du2, isect2[0], isect2[1]);
277
278 DART_SORT(isect1[0], isect1[1]);
279 DART_SORT(isect2[0], isect2[1]);
280
281 // if(isect1[1]<isect2[0] || isect2[1]<isect1[0]) return NO_CONTACT;
282
283 float res[4][3];
284 if (du0du1 > 0)
285 {
286 edge_tri_intersect(U2, U0, du2, du0, res[0]);
287 edge_tri_intersect(U2, U1, du2, du1, res[1]);
288 }
289 else if (du0du2 > 0)
290 {
291 edge_tri_intersect(U1, U0, du1, du0, res[0]);
292 edge_tri_intersect(U1, U2, du1, du2, res[1]);
293 }
294 else if (du1du2 > 0)
295 {
296 edge_tri_intersect(U0, U1, du0, du1, res[0]);
297 edge_tri_intersect(U0, U2, du0, du2, res[1]);
298 }
299 else if (du0 == 0)
300 {
301 DART_SET(res[0], U0);
302 edge_tri_intersect(U1, U2, du1, du2, res[1]);
303 }
304 else if (du1 == 0)
305 {
306 DART_SET(res[0], U1);
307 edge_tri_intersect(U0, U2, du0, du2, res[1]);
308 }
309 else if (du2 == 0)
310 {
311 DART_SET(res[0], U2);
312 edge_tri_intersect(U0, U1, du0, du1, res[1]);
313 }
314 else
315 {
316 std::cerr << "contact error" << std::endl;
317 }
318
319 if (dv0dv1 > 0)
320 {
321 edge_tri_intersect(V2, V0, dv2, dv0, res[2]);
322 edge_tri_intersect(V2, V1, dv2, dv1, res[3]);
323 }
324 else if (dv0dv2 > 0)
325 {
326 edge_tri_intersect(V1, V0, dv1, dv0, res[2]);
327 edge_tri_intersect(V1, V2, dv1, dv2, res[3]);
328 }
329 else if (dv1dv2 > 0)
330 {
331 edge_tri_intersect(V0, V1, dv0, dv1, res[2]);
332 edge_tri_intersect(V0, V2, dv0, dv2, res[3]);
333 }
334 else if (dv0 == 0)
335 {
336 DART_SET(res[2], V0);
337 edge_tri_intersect(V1, V2, dv1, dv2, res[3]);
338 }
339 else if (dv1 == 0)
340 {
341 DART_SET(res[2], V1);
342 edge_tri_intersect(V0, V2, dv0, dv2, res[3]);
343 }
344 else if (dv2 == 0)
345 {
346 DART_SET(res[2], V2);
347 edge_tri_intersect(V0, V1, dv0, dv1, res[3]);
348 }
349 else
350 {
351 std::cerr << "contact error" << std::endl;
352 }
353
354 for (int i = 3; i > 0; i--)
355 for (int j = 0; j < i; j++)
356 {
357 if (res[j][index] > res[j + 1][index])
358 {
359 for (int k = 0; k < 3; k++)
360 DART_SWAP(res[j][k], res[j + 1][k]);
361 }
362 }
363 DART_SET(res1, res[1]);
364 DART_SET(res2, res[2]);
365
366 return 1;
367}
368
369} // namespace collision
370} // namespace dart
371
372#endif // DART_COLLISION_TRITRIINTERSECTIONTEST_HPP_
std::size_t index
Definition SkelParser.cpp:1672
constexpr int NO_CONTACT
Definition tri_tri_intersection_test.hpp:135
constexpr int INTERIAL_CONTACT
Definition tri_tri_intersection_test.hpp:137
int tri_tri_intersect(float V0[3], float V1[3], float V2[3], float U0[3], float U1[3], float U2[3], float res1[3], float res2[3])
Definition tri_tri_intersection_test.hpp:157
float FABS(float x)
Definition tri_tri_intersection_test.hpp:140
constexpr double EPSILON
Definition tri_tri_intersection_test.hpp:133
void edge_tri_intersect(float V0[3], float V1[3], float DV0, float DV1, float V[3])
Definition tri_tri_intersection_test.hpp:145
constexpr int COPLANAR_CONTACT
Definition tri_tri_intersection_test.hpp:136
constexpr bool USE_EPSILON_TEST
Definition tri_tri_intersection_test.hpp:132
Definition BulletCollisionDetector.cpp:60
#define DART_CROSS(dest, v1, v2)
Definition tri_tri_intersection_test.hpp:39
#define DART_SUB(dest, v1, v2)
Definition tri_tri_intersection_test.hpp:46
#define DART_SET(dest, src)
Definition tri_tri_intersection_test.hpp:66
#define DART_COMPUTE_INTERVALS( VV0, VV1, VV2, D0, D1, D2, D0D1, D0D2, isect0, isect1)
Definition tri_tri_intersection_test.hpp:93
#define DART_SWAP(a, b)
Definition tri_tri_intersection_test.hpp:81
#define DART_SORT(a, b)
Definition tri_tri_intersection_test.hpp:72
#define DART_DOT(v1, v2)
Definition tri_tri_intersection_test.hpp:44
#define DART_MULT(dest, v, factor)
Definition tri_tri_intersection_test.hpp:56