FCL  0.6.0
Flexible Collision Library
box_box-inl.h
1 /*
2  * Software License Agreement (BSD License)
3  *
4  * Copyright (c) 2011-2014, Willow Garage, Inc.
5  * Copyright (c) 2014-2016, Open Source Robotics Foundation
6  * All rights reserved.
7  *
8  * Redistribution and use in source and binary forms, with or without
9  * modification, are permitted provided that the following conditions
10  * are met:
11  *
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  * * Neither the name of Open Source Robotics Foundation nor the names of its
19  * contributors may be used to endorse or promote products derived
20  * from this software without specific prior written permission.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
25  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
26  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
27  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
28  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
30  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
32  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
33  * POSSIBILITY OF SUCH DAMAGE.
34  */
35 
38 #ifndef FCL_NARROWPHASE_DETAIL_BOXBOX_INL_H
39 #define FCL_NARROWPHASE_DETAIL_BOXBOX_INL_H
40 
41 #include "fcl/narrowphase/detail/primitive_shape_algorithm/box_box.h"
42 
43 #include <algorithm>
44 
45 namespace fcl
46 {
47 
48 namespace detail
49 {
50 
51 //==============================================================================
52 extern template
53 void lineClosestApproach(const Vector3<double>& pa, const Vector3<double>& ua,
54  const Vector3<double>& pb, const Vector3<double>& ub,
55  double* alpha, double* beta);
56 
57 //==============================================================================
58 extern template
59 int intersectRectQuad2(double h[2], double p[8], double ret[16]);
60 
61 //==============================================================================
62 extern template
63 void cullPoints2(int n, double p[], int m, int i0, int iret[]);
64 
65 //==============================================================================
66 extern template
67 int boxBox2(
68  const Vector3<double>& side1,
69  const Transform3<double>& tf1,
70  const Vector3<double>& side2,
71  const Transform3<double>& tf2,
72  Vector3<double>& normal,
73  double* depth,
74  int* return_code,
75  int maxc,
76  std::vector<ContactPoint<double>>& contacts);
77 
78 //==============================================================================
79 extern template
80 bool boxBoxIntersect(const Box<double>& s1, const Transform3<double>& tf1,
81  const Box<double>& s2, const Transform3<double>& tf2,
82  std::vector<ContactPoint<double>>* contacts_);
83 
84 //==============================================================================
85 template <typename S>
86 void lineClosestApproach(const Vector3<S>& pa, const Vector3<S>& ua,
87  const Vector3<S>& pb, const Vector3<S>& ub,
88  S* alpha, S* beta)
89 {
90  Vector3<S> p = pb - pa;
91  S uaub = ua.dot(ub);
92  S q1 = ua.dot(p);
93  S q2 = -ub.dot(p);
94  S d = 1 - uaub * uaub;
95  if(d <= (S)(0.0001f))
96  {
97  *alpha = 0;
98  *beta = 0;
99  }
100  else
101  {
102  d = 1 / d;
103  *alpha = (q1 + uaub * q2) * d;
104  *beta = (uaub * q1 + q2) * d;
105  }
106 }
107 
108 //==============================================================================
109 template <typename S>
110 int intersectRectQuad2(S h[2], S p[8], S ret[16])
111 {
112  // q (and r) contain nq (and nr) coordinate points for the current (and
113  // chopped) polygons
114  int nq = 4, nr = 0;
115  S buffer[16];
116  S* q = p;
117  S* r = ret;
118  for(int dir = 0; dir <= 1; ++dir)
119  {
120  // direction notation: xy[0] = x axis, xy[1] = y axis
121  for(int sign = -1; sign <= 1; sign += 2)
122  {
123  // chop q along the line xy[dir] = sign*h[dir]
124  S* pq = q;
125  S* pr = r;
126  nr = 0;
127  for(int i = nq; i > 0; --i)
128  {
129  // go through all points in q and all lines between adjacent points
130  if(sign * pq[dir] < h[dir])
131  {
132  // this point is inside the chopping line
133  pr[0] = pq[0];
134  pr[1] = pq[1];
135  pr += 2;
136  nr++;
137  if(nr & 8)
138  {
139  q = r;
140  goto done;
141  }
142  }
143  S* nextq = (i > 1) ? pq+2 : q;
144  if((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir]))
145  {
146  // this line crosses the chopping line
147  pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
148  (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
149  pr[dir] = sign*h[dir];
150  pr += 2;
151  nr++;
152  if(nr & 8)
153  {
154  q = r;
155  goto done;
156  }
157  }
158  pq += 2;
159  }
160  q = r;
161  r = (q == ret) ? buffer : ret;
162  nq = nr;
163  }
164  }
165 
166  done:
167  if(q != ret) memcpy(ret, q, nr*2*sizeof(S));
168  return nr;
169 }
170 
171 //==============================================================================
172 template <typename S>
173 void cullPoints2(int n, S p[], int m, int i0, int iret[])
174 {
175  // compute the centroid of the polygon in cx,cy
176  S a, cx, cy, q;
177  switch(n)
178  {
179  case 1:
180  cx = p[0];
181  cy = p[1];
182  break;
183  case 2:
184  cx = 0.5 * (p[0] + p[2]);
185  cy = 0.5 * (p[1] + p[3]);
186  break;
187  default:
188  a = 0;
189  cx = 0;
190  cy = 0;
191  for(int i = 0; i < n-1; ++i)
192  {
193  q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
194  a += q;
195  cx += q*(p[i*2]+p[i*2+2]);
196  cy += q*(p[i*2+1]+p[i*2+3]);
197  }
198  q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
199  if(std::abs(a+q) > std::numeric_limits<S>::epsilon())
200  a = 1/(3*(a+q));
201  else
202  a= 1e18f;
203 
204  cx = a*(cx + q*(p[n*2-2]+p[0]));
205  cy = a*(cy + q*(p[n*2-1]+p[1]));
206  }
207 
208 
209  // compute the angle of each point w.r.t. the centroid
210  S A[8];
211  for(int i = 0; i < n; ++i)
212  A[i] = atan2(p[i*2+1]-cy,p[i*2]-cx);
213 
214  // search for points that have angles closest to A[i0] + i*(2*pi/m).
215  int avail[8];
216  for(int i = 0; i < n; ++i) avail[i] = 1;
217  avail[i0] = 0;
218  iret[0] = i0;
219  iret++;
220  const S pi = constants<S>::pi();
221  for(int j = 1; j < m; ++j)
222  {
223  a = j*(2*pi/m) + A[i0];
224  if (a > pi) a -= 2*pi;
225  S maxdiff= 1e9, diff;
226 
227  *iret = i0; // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
228  for(int i = 0; i < n; ++i)
229  {
230  if(avail[i])
231  {
232  diff = std::abs(A[i]-a);
233  if(diff > pi) diff = 2*pi - diff;
234  if(diff < maxdiff)
235  {
236  maxdiff = diff;
237  *iret = i;
238  }
239  }
240  }
241  avail[*iret] = 0;
242  iret++;
243  }
244 }
245 
246 //==============================================================================
247 template <typename S, typename DerivedA, typename DerivedB>
248 int boxBox2(
249  const Vector3<S>& side1,
250  const Eigen::MatrixBase<DerivedA>& R1,
251  const Eigen::MatrixBase<DerivedB>& T1,
252  const Vector3<S>& side2,
253  const Eigen::MatrixBase<DerivedA>& R2,
254  const Eigen::MatrixBase<DerivedB>& T2,
255  Vector3<S>& normal,
256  S* depth,
257  int* return_code,
258  int maxc,
259  std::vector<ContactPoint<S>>& contacts)
260 {
261  const S fudge_factor = S(1.05);
262  Vector3<S> normalC;
263  S s, s2, l;
264  int invert_normal, code;
265 
266  Vector3<S> p = T2 - T1; // get vector from centers of box 1 to box 2, relative to box 1
267  Vector3<S> pp = R1.transpose() * p; // get pp = p relative to body 1
268 
269  // get side lengths / 2
270  Vector3<S> A = side1 * 0.5;
271  Vector3<S> B = side2 * 0.5;
272 
273  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
274  Matrix3<S> R = R1.transpose() * R2;
275  Matrix3<S> Q = R.cwiseAbs();
276 
277 
278  // for all 15 possible separating axes:
279  // * see if the axis separates the boxes. if so, return 0.
280  // * find the depth of the penetration along the separating axis (s2)
281  // * if this is the largest depth so far, record it.
282  // the normal vector will be set to the separating axis with the smallest
283  // depth. note: normalR is set to point to a column of R1 or R2 if that is
284  // the smallest depth normal so far. otherwise normalR is 0 and normalC is
285  // set to a vector relative to body 1. invert_normal is 1 if the sign of
286  // the normal should be flipped.
287 
288  int best_col_id = -1;
289  const Eigen::MatrixBase<DerivedA>* normalR = 0;
290  S tmp = 0;
291 
292  s = - std::numeric_limits<S>::max();
293  invert_normal = 0;
294  code = 0;
295 
296  // separating axis = u1, u2, u3
297  tmp = pp[0];
298  s2 = std::abs(tmp) - (Q.row(0).dot(B) + A[0]);
299  if(s2 > 0) { *return_code = 0; return 0; }
300  if(s2 > s)
301  {
302  s = s2;
303  best_col_id = 0;
304  normalR = &R1;
305  invert_normal = (tmp < 0);
306  code = 1;
307  }
308 
309  tmp = pp[1];
310  s2 = std::abs(tmp) - (Q.row(1).dot(B) + A[1]);
311  if(s2 > 0) { *return_code = 0; return 0; }
312  if(s2 > s)
313  {
314  s = s2;
315  best_col_id = 1;
316  normalR = &R1;
317  invert_normal = (tmp < 0);
318  code = 2;
319  }
320 
321  tmp = pp[2];
322  s2 = std::abs(tmp) - (Q.row(2).dot(B) + A[2]);
323  if(s2 > 0) { *return_code = 0; return 0; }
324  if(s2 > s)
325  {
326  s = s2;
327  best_col_id = 2;
328  normalR = &R1;
329  invert_normal = (tmp < 0);
330  code = 3;
331  }
332 
333  // separating axis = v1, v2, v3
334  tmp = R2.col(0).dot(p);
335  s2 = std::abs(tmp) - (Q.col(0).dot(A) + B[0]);
336  if(s2 > 0) { *return_code = 0; return 0; }
337  if(s2 > s)
338  {
339  s = s2;
340  best_col_id = 0;
341  normalR = &R2;
342  invert_normal = (tmp < 0);
343  code = 4;
344  }
345 
346  tmp = R2.col(1).dot(p);
347  s2 = std::abs(tmp) - (Q.col(1).dot(A) + B[1]);
348  if(s2 > 0) { *return_code = 0; return 0; }
349  if(s2 > s)
350  {
351  s = s2;
352  best_col_id = 1;
353  normalR = &R2;
354  invert_normal = (tmp < 0);
355  code = 5;
356  }
357 
358  tmp = R2.col(2).dot(p);
359  s2 = std::abs(tmp) - (Q.col(2).dot(A) + B[2]);
360  if(s2 > 0) { *return_code = 0; return 0; }
361  if(s2 > s)
362  {
363  s = s2;
364  best_col_id = 2;
365  normalR = &R2;
366  invert_normal = (tmp < 0);
367  code = 6;
368  }
369 
370 
371  S fudge2(1.0e-6);
372  Q.array() += fudge2;
373 
374  Vector3<S> n;
375  S eps = std::numeric_limits<S>::epsilon();
376 
377  // separating axis = u1 x (v1,v2,v3)
378  tmp = pp[2] * R(1, 0) - pp[1] * R(2, 0);
379  s2 = std::abs(tmp) - (A[1] * Q(2, 0) + A[2] * Q(1, 0) + B[1] * Q(0, 2) + B[2] * Q(0, 1));
380  if(s2 > 0) { *return_code = 0; return 0; }
381  n = Vector3<S>(0, -R(2, 0), R(1, 0));
382  l = n.norm();
383  if(l > eps)
384  {
385  s2 /= l;
386  if(s2 * fudge_factor > s)
387  {
388  s = s2;
389  best_col_id = -1;
390  normalC = n / l;
391  invert_normal = (tmp < 0);
392  code = 7;
393  }
394  }
395 
396  tmp = pp[2] * R(1, 1) - pp[1] * R(2, 1);
397  s2 = std::abs(tmp) - (A[1] * Q(2, 1) + A[2] * Q(1, 1) + B[0] * Q(0, 2) + B[2] * Q(0, 0));
398  if(s2 > 0) { *return_code = 0; return 0; }
399  n = Vector3<S>(0, -R(2, 1), R(1, 1));
400  l = n.norm();
401  if(l > eps)
402  {
403  s2 /= l;
404  if(s2 * fudge_factor > s)
405  {
406  s = s2;
407  best_col_id = -1;
408  normalC = n / l;
409  invert_normal = (tmp < 0);
410  code = 8;
411  }
412  }
413 
414  tmp = pp[2] * R(1, 2) - pp[1] * R(2, 2);
415  s2 = std::abs(tmp) - (A[1] * Q(2, 2) + A[2] * Q(1, 2) + B[0] * Q(0, 1) + B[1] * Q(0, 0));
416  if(s2 > 0) { *return_code = 0; return 0; }
417  n = Vector3<S>(0, -R(2, 2), R(1, 2));
418  l = n.norm();
419  if(l > eps)
420  {
421  s2 /= l;
422  if(s2 * fudge_factor > s)
423  {
424  s = s2;
425  best_col_id = -1;
426  normalC = n / l;
427  invert_normal = (tmp < 0);
428  code = 9;
429  }
430  }
431 
432  // separating axis = u2 x (v1,v2,v3)
433  tmp = pp[0] * R(2, 0) - pp[2] * R(0, 0);
434  s2 = std::abs(tmp) - (A[0] * Q(2, 0) + A[2] * Q(0, 0) + B[1] * Q(1, 2) + B[2] * Q(1, 1));
435  if(s2 > 0) { *return_code = 0; return 0; }
436  n = Vector3<S>(R(2, 0), 0, -R(0, 0));
437  l = n.norm();
438  if(l > eps)
439  {
440  s2 /= l;
441  if(s2 * fudge_factor > s)
442  {
443  s = s2;
444  best_col_id = -1;
445  normalC = n / l;
446  invert_normal = (tmp < 0);
447  code = 10;
448  }
449  }
450 
451  tmp = pp[0] * R(2, 1) - pp[2] * R(0, 1);
452  s2 = std::abs(tmp) - (A[0] * Q(2, 1) + A[2] * Q(0, 1) + B[0] * Q(1, 2) + B[2] * Q(1, 0));
453  if(s2 > 0) { *return_code = 0; return 0; }
454  n = Vector3<S>(R(2, 1), 0, -R(0, 1));
455  l = n.norm();
456  if(l > eps)
457  {
458  s2 /= l;
459  if(s2 * fudge_factor > s)
460  {
461  s = s2;
462  best_col_id = -1;
463  normalC = n / l;
464  invert_normal = (tmp < 0);
465  code = 11;
466  }
467  }
468 
469  tmp = pp[0] * R(2, 2) - pp[2] * R(0, 2);
470  s2 = std::abs(tmp) - (A[0] * Q(2, 2) + A[2] * Q(0, 2) + B[0] * Q(1, 1) + B[1] * Q(1, 0));
471  if(s2 > 0) { *return_code = 0; return 0; }
472  n = Vector3<S>(R(2, 2), 0, -R(0, 2));
473  l = n.norm();
474  if(l > eps)
475  {
476  s2 /= l;
477  if(s2 * fudge_factor > s)
478  {
479  s = s2;
480  best_col_id = -1;
481  normalC = n / l;
482  invert_normal = (tmp < 0);
483  code = 12;
484  }
485  }
486 
487  // separating axis = u3 x (v1,v2,v3)
488  tmp = pp[1] * R(0, 0) - pp[0] * R(1, 0);
489  s2 = std::abs(tmp) - (A[0] * Q(1, 0) + A[1] * Q(0, 0) + B[1] * Q(2, 2) + B[2] * Q(2, 1));
490  if(s2 > 0) { *return_code = 0; return 0; }
491  n = Vector3<S>(-R(1, 0), R(0, 0), 0);
492  l = n.norm();
493  if(l > eps)
494  {
495  s2 /= l;
496  if(s2 * fudge_factor > s)
497  {
498  s = s2;
499  best_col_id = -1;
500  normalC = n / l;
501  invert_normal = (tmp < 0);
502  code = 13;
503  }
504  }
505 
506  tmp = pp[1] * R(0, 1) - pp[0] * R(1, 1);
507  s2 = std::abs(tmp) - (A[0] * Q(1, 1) + A[1] * Q(0, 1) + B[0] * Q(2, 2) + B[2] * Q(2, 0));
508  if(s2 > 0) { *return_code = 0; return 0; }
509  n = Vector3<S>(-R(1, 1), R(0, 1), 0);
510  l = n.norm();
511  if(l > eps)
512  {
513  s2 /= l;
514  if(s2 * fudge_factor > s)
515  {
516  s = s2;
517  best_col_id = -1;
518  normalC = n / l;
519  invert_normal = (tmp < 0);
520  code = 14;
521  }
522  }
523 
524  tmp = pp[1] * R(0, 2) - pp[0] * R(1, 2);
525  s2 = std::abs(tmp) - (A[0] * Q(1, 2) + A[1] * Q(0, 2) + B[0] * Q(2, 1) + B[1] * Q(2, 0));
526  if(s2 > 0) { *return_code = 0; return 0; }
527  n = Vector3<S>(-R(1, 2), R(0, 2), 0);
528  l = n.norm();
529  if(l > eps)
530  {
531  s2 /= l;
532  if(s2 * fudge_factor > s)
533  {
534  s = s2;
535  best_col_id = -1;
536  normalC = n / l;
537  invert_normal = (tmp < 0);
538  code = 15;
539  }
540  }
541 
542 
543 
544  if (!code) { *return_code = code; return 0; }
545 
546  // if we get to this point, the boxes interpenetrate. compute the normal
547  // in global coordinates.
548  if(best_col_id != -1)
549  normal = normalR->col(best_col_id);
550  else
551  normal = R1 * normalC;
552 
553  if(invert_normal)
554  normal = -normal;
555 
556  *depth = -s; // s is negative when the boxes are in collision
557 
558  // compute contact point(s)
559 
560  if(code > 6)
561  {
562  // an edge from box 1 touches an edge from box 2.
563  // find a point pa on the intersecting edge of box 1
564  Vector3<S> pa(T1);
565  S sign;
566 
567  for(int j = 0; j < 3; ++j)
568  {
569  sign = (R1.col(j).dot(normal) > 0) ? 1 : -1;
570  pa += R1.col(j) * (A[j] * sign);
571  }
572 
573  // find a point pb on the intersecting edge of box 2
574  Vector3<S> pb(T2);
575 
576  for(int j = 0; j < 3; ++j)
577  {
578  sign = (R2.col(j).dot(normal) > 0) ? -1 : 1;
579  pb += R2.col(j) * (B[j] * sign);
580  }
581 
582  S alpha, beta;
583  Vector3<S> ua(R1.col((code-7)/3));
584  Vector3<S> ub(R2.col((code-7)%3));
585 
586  lineClosestApproach(pa, ua, pb, ub, &alpha, &beta);
587  pa += ua * alpha;
588  pb += ub * beta;
589 
590 
591  // Vector3<S> pointInWorld((pa + pb) * 0.5);
592  // contacts.push_back(ContactPoint<S>(-normal, pointInWorld, -*depth));
593  contacts.emplace_back(normal, pb, -*depth);
594  *return_code = code;
595 
596  return 1;
597  }
598 
599  // okay, we have a face-something intersection (because the separating
600  // axis is perpendicular to a face). define face 'a' to be the reference
601  // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
602  // the incident face (the closest face of the other box).
603 
604  const Eigen::MatrixBase<DerivedA> *Ra, *Rb;
605  const Eigen::MatrixBase<DerivedB> *pa, *pb;
606  const Vector3<S> *Sa, *Sb;
607 
608  if(code <= 3)
609  {
610  Ra = &R1;
611  Rb = &R2;
612  pa = &T1;
613  pb = &T2;
614  Sa = &A;
615  Sb = &B;
616  }
617  else
618  {
619  Ra = &R2;
620  Rb = &R1;
621  pa = &T2;
622  pb = &T1;
623  Sa = &B;
624  Sb = &A;
625  }
626 
627  // nr = normal vector of reference face dotted with axes of incident box.
628  // anr = absolute values of nr.
629  Vector3<S> normal2, nr, anr;
630  if(code <= 3)
631  normal2 = normal;
632  else
633  normal2 = -normal;
634 
635  nr = Rb->transpose() * normal2;
636  anr = nr.cwiseAbs();
637 
638  // find the largest compontent of anr: this corresponds to the normal
639  // for the indident face. the other axis numbers of the indicent face
640  // are stored in a1,a2.
641  int lanr, a1, a2;
642  if(anr[1] > anr[0])
643  {
644  if(anr[1] > anr[2])
645  {
646  a1 = 0;
647  lanr = 1;
648  a2 = 2;
649  }
650  else
651  {
652  a1 = 0;
653  a2 = 1;
654  lanr = 2;
655  }
656  }
657  else
658  {
659  if(anr[0] > anr[2])
660  {
661  lanr = 0;
662  a1 = 1;
663  a2 = 2;
664  }
665  else
666  {
667  a1 = 0;
668  a2 = 1;
669  lanr = 2;
670  }
671  }
672 
673  // compute center point of incident face, in reference-face coordinates
674  Vector3<S> center;
675  if(nr[lanr] < 0)
676  center = (*pb) - (*pa) + Rb->col(lanr) * ((*Sb)[lanr]);
677  else
678  center = (*pb) - (*pa) - Rb->col(lanr) * ((*Sb)[lanr]);
679 
680  // find the normal and non-normal axis numbers of the reference box
681  int codeN, code1, code2;
682  if(code <= 3)
683  codeN = code-1;
684  else codeN = code-4;
685 
686  if(codeN == 0)
687  {
688  code1 = 1;
689  code2 = 2;
690  }
691  else if(codeN == 1)
692  {
693  code1 = 0;
694  code2 = 2;
695  }
696  else
697  {
698  code1 = 0;
699  code2 = 1;
700  }
701 
702  // find the four corners of the incident face, in reference-face coordinates
703  S quad[8]; // 2D coordinate of incident face (x,y pairs)
704  S c1, c2, m11, m12, m21, m22;
705  c1 = Ra->col(code1).dot(center);
706  c2 = Ra->col(code2).dot(center);
707  // optimize this? - we have already computed this data above, but it is not
708  // stored in an easy-to-index format. for now it's quicker just to recompute
709  // the four dot products.
710  Vector3<S> tempRac = Ra->col(code1);
711  m11 = Rb->col(a1).dot(tempRac);
712  m12 = Rb->col(a2).dot(tempRac);
713  tempRac = Ra->col(code2);
714  m21 = Rb->col(a1).dot(tempRac);
715  m22 = Rb->col(a2).dot(tempRac);
716 
717  S k1 = m11 * (*Sb)[a1];
718  S k2 = m21 * (*Sb)[a1];
719  S k3 = m12 * (*Sb)[a2];
720  S k4 = m22 * (*Sb)[a2];
721  quad[0] = c1 - k1 - k3;
722  quad[1] = c2 - k2 - k4;
723  quad[2] = c1 - k1 + k3;
724  quad[3] = c2 - k2 + k4;
725  quad[4] = c1 + k1 + k3;
726  quad[5] = c2 + k2 + k4;
727  quad[6] = c1 + k1 - k3;
728  quad[7] = c2 + k2 - k4;
729 
730  // find the size of the reference face
731  S rect[2];
732  rect[0] = (*Sa)[code1];
733  rect[1] = (*Sa)[code2];
734 
735  // intersect the incident and reference faces
736  S ret[16];
737  int n_intersect = intersectRectQuad2(rect, quad, ret);
738  if(n_intersect < 1) { *return_code = code; return 0; } // this should never happen
739 
740  // convert the intersection points into reference-face coordinates,
741  // and compute the contact position and depth for each point. only keep
742  // those points that have a positive (penetrating) depth. delete points in
743  // the 'ret' array as necessary so that 'point' and 'ret' correspond.
744  Vector3<S> points[8]; // penetrating contact points
745  S dep[8]; // depths for those points
746  S det1 = 1.f/(m11*m22 - m12*m21);
747  m11 *= det1;
748  m12 *= det1;
749  m21 *= det1;
750  m22 *= det1;
751  int cnum = 0; // number of penetrating contact points found
752  for(int j = 0; j < n_intersect; ++j)
753  {
754  S k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
755  S k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
756  points[cnum] = center + Rb->col(a1) * k1 + Rb->col(a2) * k2;
757  dep[cnum] = (*Sa)[codeN] - normal2.dot(points[cnum]);
758  if(dep[cnum] >= 0)
759  {
760  ret[cnum*2] = ret[j*2];
761  ret[cnum*2+1] = ret[j*2+1];
762  cnum++;
763  }
764  }
765  if(cnum < 1) { *return_code = code; return 0; } // this should never happen
766 
767  // we can't generate more contacts than we actually have
768  if(maxc > cnum) maxc = cnum;
769  if(maxc < 1) maxc = 1;
770 
771  if(cnum <= maxc)
772  {
773  if(code<4)
774  {
775  // we have less contacts than we need, so we use them all
776  for(int j = 0; j < cnum; ++j)
777  {
778  Vector3<S> pointInWorld = points[j] + (*pa);
779  contacts.emplace_back(normal, pointInWorld, -dep[j]);
780  }
781  }
782  else
783  {
784  // we have less contacts than we need, so we use them all
785  for(int j = 0; j < cnum; ++j)
786  {
787  Vector3<S> pointInWorld = points[j] + (*pa) - normal * dep[j];
788  contacts.emplace_back(normal, pointInWorld, -dep[j]);
789  }
790  }
791  }
792  else
793  {
794  // we have more contacts than are wanted, some of them must be culled.
795  // find the deepest point, it is always the first contact.
796  int i1 = 0;
797  S maxdepth = dep[0];
798  for(int i = 1; i < cnum; ++i)
799  {
800  if(dep[i] > maxdepth)
801  {
802  maxdepth = dep[i];
803  i1 = i;
804  }
805  }
806 
807  int iret[8];
808  cullPoints2(cnum, ret, maxc, i1, iret);
809 
810  for(int j = 0; j < maxc; ++j)
811  {
812  Vector3<S> posInWorld = points[iret[j]] + (*pa);
813  if(code < 4)
814  contacts.emplace_back(normal, posInWorld, -dep[iret[j]]);
815  else
816  contacts.emplace_back(normal, posInWorld - normal * dep[iret[j]], -dep[iret[j]]);
817  }
818  cnum = maxc;
819  }
820 
821  *return_code = code;
822  return cnum;
823 }
824 
825 //==============================================================================
826 template <typename S>
827 int boxBox2(
828  const Vector3<S>& side1,
829  const Transform3<S>& tf1,
830  const Vector3<S>& side2,
831  const Transform3<S>& tf2,
832  Vector3<S>& normal,
833  S* depth,
834  int* return_code,
835  int maxc,
836  std::vector<ContactPoint<S>>& contacts)
837 {
838  const S fudge_factor = S(1.05);
839  Vector3<S> normalC;
840 
841  const Vector3<S> p = tf2.translation() - tf1.translation(); // get vector from centers of box 1 to box 2, relative to box 1
842  const Vector3<S> pp = tf1.linear().transpose() * p; // get pp = p relative to body 1
843 
844  // get side lengths / 2
845  const Vector3<S> A = side1 * 0.5;
846  const Vector3<S> B = side2 * 0.5;
847 
848  // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
849  const Matrix3<S> R = tf1.linear().transpose() * tf2.linear();
850  Matrix3<S> Q = R.cwiseAbs();
851 
852  // for all 15 possible separating axes:
853  // * see if the axis separates the boxes. if so, return 0.
854  // * find the depth of the penetration along the separating axis (s2)
855  // * if this is the largest depth so far, record it.
856  // the normal vector will be set to the separating axis with the smallest
857  // depth. note: normalR is set to point to a column of R1 or R2 if that is
858  // the smallest depth normal so far. otherwise normalR is 0 and normalC is
859  // set to a vector relative to body 1. invert_normal is 1 if the sign of
860  // the normal should be flipped.
861 
862  int best_col_id = -1;
863  const Transform3<S>* normalT = nullptr;
864 
865  S s = - std::numeric_limits<S>::max();
866  int invert_normal = 0;
867  int code = 0;
868 
869  // separating axis = u1, u2, u3
870  S tmp = pp[0];
871  S s2 = std::abs(tmp) - (Q.row(0).dot(B) + A[0]);
872  if(s2 > 0) { *return_code = 0; return 0; }
873  if(s2 > s)
874  {
875  s = s2;
876  best_col_id = 0;
877  normalT = &tf1;
878  invert_normal = (tmp < 0);
879  code = 1;
880  }
881 
882  tmp = pp[1];
883  s2 = std::abs(tmp) - (Q.row(1).dot(B) + A[1]);
884  if(s2 > 0) { *return_code = 0; return 0; }
885  if(s2 > s)
886  {
887  s = s2;
888  best_col_id = 1;
889  normalT = &tf1;
890  invert_normal = (tmp < 0);
891  code = 2;
892  }
893 
894  tmp = pp[2];
895  s2 = std::abs(tmp) - (Q.row(2).dot(B) + A[2]);
896  if(s2 > 0) { *return_code = 0; return 0; }
897  if(s2 > s)
898  {
899  s = s2;
900  best_col_id = 2;
901  normalT = &tf1;
902  invert_normal = (tmp < 0);
903  code = 3;
904  }
905 
906  // separating axis = v1, v2, v3
907  tmp = tf2.linear().col(0).dot(p);
908  s2 = std::abs(tmp) - (Q.col(0).dot(A) + B[0]);
909  if(s2 > 0) { *return_code = 0; return 0; }
910  if(s2 > s)
911  {
912  s = s2;
913  best_col_id = 0;
914  normalT = &tf2;
915  invert_normal = (tmp < 0);
916  code = 4;
917  }
918 
919  tmp = tf2.linear().col(1).dot(p);
920  s2 = std::abs(tmp) - (Q.col(1).dot(A) + B[1]);
921  if(s2 > 0) { *return_code = 0; return 0; }
922  if(s2 > s)
923  {
924  s = s2;
925  best_col_id = 1;
926  normalT = &tf2;
927  invert_normal = (tmp < 0);
928  code = 5;
929  }
930 
931  tmp = tf2.linear().col(2).dot(p);
932  s2 = std::abs(tmp) - (Q.col(2).dot(A) + B[2]);
933  if(s2 > 0) { *return_code = 0; return 0; }
934  if(s2 > s)
935  {
936  s = s2;
937  best_col_id = 2;
938  normalT = &tf2;
939  invert_normal = (tmp < 0);
940  code = 6;
941  }
942 
943 
944  S fudge2(1.0e-6);
945  Q.array() += fudge2;
946 
947  Vector3<S> n;
948  S eps = std::numeric_limits<S>::epsilon();
949 
950  // separating axis = u1 x (v1,v2,v3)
951  tmp = pp[2] * R(1, 0) - pp[1] * R(2, 0);
952  s2 = std::abs(tmp) - (A[1] * Q(2, 0) + A[2] * Q(1, 0) + B[1] * Q(0, 2) + B[2] * Q(0, 1));
953  if(s2 > 0) { *return_code = 0; return 0; }
954  n = Vector3<S>(0, -R(2, 0), R(1, 0));
955  S l = n.norm();
956  if(l > eps)
957  {
958  s2 /= l;
959  if(s2 * fudge_factor > s)
960  {
961  s = s2;
962  best_col_id = -1;
963  normalC = n / l;
964  invert_normal = (tmp < 0);
965  code = 7;
966  }
967  }
968 
969  tmp = pp[2] * R(1, 1) - pp[1] * R(2, 1);
970  s2 = std::abs(tmp) - (A[1] * Q(2, 1) + A[2] * Q(1, 1) + B[0] * Q(0, 2) + B[2] * Q(0, 0));
971  if(s2 > 0) { *return_code = 0; return 0; }
972  n = Vector3<S>(0, -R(2, 1), R(1, 1));
973  l = n.norm();
974  if(l > eps)
975  {
976  s2 /= l;
977  if(s2 * fudge_factor > s)
978  {
979  s = s2;
980  best_col_id = -1;
981  normalC = n / l;
982  invert_normal = (tmp < 0);
983  code = 8;
984  }
985  }
986 
987  tmp = pp[2] * R(1, 2) - pp[1] * R(2, 2);
988  s2 = std::abs(tmp) - (A[1] * Q(2, 2) + A[2] * Q(1, 2) + B[0] * Q(0, 1) + B[1] * Q(0, 0));
989  if(s2 > 0) { *return_code = 0; return 0; }
990  n = Vector3<S>(0, -R(2, 2), R(1, 2));
991  l = n.norm();
992  if(l > eps)
993  {
994  s2 /= l;
995  if(s2 * fudge_factor > s)
996  {
997  s = s2;
998  best_col_id = -1;
999  normalC = n / l;
1000  invert_normal = (tmp < 0);
1001  code = 9;
1002  }
1003  }
1004 
1005  // separating axis = u2 x (v1,v2,v3)
1006  tmp = pp[0] * R(2, 0) - pp[2] * R(0, 0);
1007  s2 = std::abs(tmp) - (A[0] * Q(2, 0) + A[2] * Q(0, 0) + B[1] * Q(1, 2) + B[2] * Q(1, 1));
1008  if(s2 > 0) { *return_code = 0; return 0; }
1009  n = Vector3<S>(R(2, 0), 0, -R(0, 0));
1010  l = n.norm();
1011  if(l > eps)
1012  {
1013  s2 /= l;
1014  if(s2 * fudge_factor > s)
1015  {
1016  s = s2;
1017  best_col_id = -1;
1018  normalC = n / l;
1019  invert_normal = (tmp < 0);
1020  code = 10;
1021  }
1022  }
1023 
1024  tmp = pp[0] * R(2, 1) - pp[2] * R(0, 1);
1025  s2 = std::abs(tmp) - (A[0] * Q(2, 1) + A[2] * Q(0, 1) + B[0] * Q(1, 2) + B[2] * Q(1, 0));
1026  if(s2 > 0) { *return_code = 0; return 0; }
1027  n = Vector3<S>(R(2, 1), 0, -R(0, 1));
1028  l = n.norm();
1029  if(l > eps)
1030  {
1031  s2 /= l;
1032  if(s2 * fudge_factor > s)
1033  {
1034  s = s2;
1035  best_col_id = -1;
1036  normalC = n / l;
1037  invert_normal = (tmp < 0);
1038  code = 11;
1039  }
1040  }
1041 
1042  tmp = pp[0] * R(2, 2) - pp[2] * R(0, 2);
1043  s2 = std::abs(tmp) - (A[0] * Q(2, 2) + A[2] * Q(0, 2) + B[0] * Q(1, 1) + B[1] * Q(1, 0));
1044  if(s2 > 0) { *return_code = 0; return 0; }
1045  n = Vector3<S>(R(2, 2), 0, -R(0, 2));
1046  l = n.norm();
1047  if(l > eps)
1048  {
1049  s2 /= l;
1050  if(s2 * fudge_factor > s)
1051  {
1052  s = s2;
1053  best_col_id = -1;
1054  normalC = n / l;
1055  invert_normal = (tmp < 0);
1056  code = 12;
1057  }
1058  }
1059 
1060  // separating axis = u3 x (v1,v2,v3)
1061  tmp = pp[1] * R(0, 0) - pp[0] * R(1, 0);
1062  s2 = std::abs(tmp) - (A[0] * Q(1, 0) + A[1] * Q(0, 0) + B[1] * Q(2, 2) + B[2] * Q(2, 1));
1063  if(s2 > 0) { *return_code = 0; return 0; }
1064  n = Vector3<S>(-R(1, 0), R(0, 0), 0);
1065  l = n.norm();
1066  if(l > eps)
1067  {
1068  s2 /= l;
1069  if(s2 * fudge_factor > s)
1070  {
1071  s = s2;
1072  best_col_id = -1;
1073  normalC = n / l;
1074  invert_normal = (tmp < 0);
1075  code = 13;
1076  }
1077  }
1078 
1079  tmp = pp[1] * R(0, 1) - pp[0] * R(1, 1);
1080  s2 = std::abs(tmp) - (A[0] * Q(1, 1) + A[1] * Q(0, 1) + B[0] * Q(2, 2) + B[2] * Q(2, 0));
1081  if(s2 > 0) { *return_code = 0; return 0; }
1082  n = Vector3<S>(-R(1, 1), R(0, 1), 0);
1083  l = n.norm();
1084  if(l > eps)
1085  {
1086  s2 /= l;
1087  if(s2 * fudge_factor > s)
1088  {
1089  s = s2;
1090  best_col_id = -1;
1091  normalC = n / l;
1092  invert_normal = (tmp < 0);
1093  code = 14;
1094  }
1095  }
1096 
1097  tmp = pp[1] * R(0, 2) - pp[0] * R(1, 2);
1098  s2 = std::abs(tmp) - (A[0] * Q(1, 2) + A[1] * Q(0, 2) + B[0] * Q(2, 1) + B[1] * Q(2, 0));
1099  if(s2 > 0) { *return_code = 0; return 0; }
1100  n = Vector3<S>(-R(1, 2), R(0, 2), 0);
1101  l = n.norm();
1102  if(l > eps)
1103  {
1104  s2 /= l;
1105  if(s2 * fudge_factor > s)
1106  {
1107  s = s2;
1108  best_col_id = -1;
1109  normalC = n / l;
1110  invert_normal = (tmp < 0);
1111  code = 15;
1112  }
1113  }
1114 
1115 
1116 
1117  if (!code) { *return_code = code; return 0; }
1118 
1119  // if we get to this point, the boxes interpenetrate. compute the normal
1120  // in global coordinates.
1121  if(best_col_id != -1)
1122  normal = normalT->linear().col(best_col_id);
1123  else
1124  normal = tf1.linear() * normalC;
1125 
1126  if(invert_normal)
1127  normal = -normal;
1128 
1129  *depth = -s; // s is negative when the boxes are in collision
1130 
1131  // compute contact point(s)
1132 
1133  if(code > 6)
1134  {
1135  // an edge from box 1 touches an edge from box 2.
1136  // find a point pa on the intersecting edge of box 1
1137  Vector3<S> pa(tf1.translation());
1138  S sign;
1139 
1140  for(int j = 0; j < 3; ++j)
1141  {
1142  sign = (tf1.linear().col(j).dot(normal) > 0) ? 1 : -1;
1143  pa += tf1.linear().col(j) * (A[j] * sign);
1144  }
1145 
1146  // find a point pb on the intersecting edge of box 2
1147  Vector3<S> pb(tf2.translation());
1148 
1149  for(int j = 0; j < 3; ++j)
1150  {
1151  sign = (tf2.linear().col(j).dot(normal) > 0) ? -1 : 1;
1152  pb += tf2.linear().col(j) * (B[j] * sign);
1153  }
1154 
1155  S alpha, beta;
1156  Vector3<S> ua(tf1.linear().col((code-7)/3));
1157  Vector3<S> ub(tf2.linear().col((code-7)%3));
1158 
1159  lineClosestApproach(pa, ua, pb, ub, &alpha, &beta);
1160  pa += ua * alpha;
1161  pb += ub * beta;
1162 
1163 
1164  // Vector3<S> pointInWorld((pa + pb) * 0.5);
1165  // contacts.push_back(ContactPoint<S>(-normal, pointInWorld, -*depth));
1166  contacts.emplace_back(normal, pb, -*depth);
1167  *return_code = code;
1168 
1169  return 1;
1170  }
1171 
1172  // okay, we have a face-something intersection (because the separating
1173  // axis is perpendicular to a face). define face 'a' to be the reference
1174  // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
1175  // the incident face (the closest face of the other box).
1176 
1177  const Transform3<S> *Ta, *Tb;
1178  const Vector3<S> *Sa, *Sb;
1179 
1180  if(code <= 3)
1181  {
1182  Ta = &tf1;
1183  Tb = &tf2;
1184  Sa = &A;
1185  Sb = &B;
1186  }
1187  else
1188  {
1189  Ta = &tf2;
1190  Tb = &tf1;
1191  Sa = &B;
1192  Sb = &A;
1193  }
1194 
1195  // nr = normal vector of reference face dotted with axes of incident box.
1196  // anr = absolute values of nr.
1197  Vector3<S> normal2, nr, anr;
1198  if(code <= 3)
1199  normal2 = normal;
1200  else
1201  normal2 = -normal;
1202 
1203  nr = Tb->linear().transpose() * normal2;
1204  anr = nr.cwiseAbs();
1205 
1206  // find the largest compontent of anr: this corresponds to the normal
1207  // for the indident face. the other axis numbers of the indicent face
1208  // are stored in a1,a2.
1209  int lanr, a1, a2;
1210  if(anr[1] > anr[0])
1211  {
1212  if(anr[1] > anr[2])
1213  {
1214  a1 = 0;
1215  lanr = 1;
1216  a2 = 2;
1217  }
1218  else
1219  {
1220  a1 = 0;
1221  a2 = 1;
1222  lanr = 2;
1223  }
1224  }
1225  else
1226  {
1227  if(anr[0] > anr[2])
1228  {
1229  lanr = 0;
1230  a1 = 1;
1231  a2 = 2;
1232  }
1233  else
1234  {
1235  a1 = 0;
1236  a2 = 1;
1237  lanr = 2;
1238  }
1239  }
1240 
1241  // compute center point of incident face, in reference-face coordinates
1242  Vector3<S> center;
1243  if(nr[lanr] < 0)
1244  center = Tb->translation() - Ta->translation() + Tb->linear().col(lanr) * ((*Sb)[lanr]);
1245  else
1246  center = Tb->translation() - Ta->translation() - Tb->linear().col(lanr) * ((*Sb)[lanr]);
1247 
1248  // find the normal and non-normal axis numbers of the reference box
1249  int codeN, code1, code2;
1250  if(code <= 3)
1251  codeN = code-1;
1252  else codeN = code-4;
1253 
1254  if(codeN == 0)
1255  {
1256  code1 = 1;
1257  code2 = 2;
1258  }
1259  else if(codeN == 1)
1260  {
1261  code1 = 0;
1262  code2 = 2;
1263  }
1264  else
1265  {
1266  code1 = 0;
1267  code2 = 1;
1268  }
1269 
1270  // find the four corners of the incident face, in reference-face coordinates
1271  S quad[8]; // 2D coordinate of incident face (x,y pairs)
1272  S c1, c2, m11, m12, m21, m22;
1273  c1 = Ta->linear().col(code1).dot(center);
1274  c2 = Ta->linear().col(code2).dot(center);
1275  // optimize this? - we have already computed this data above, but it is not
1276  // stored in an easy-to-index format. for now it's quicker just to recompute
1277  // the four dot products.
1278  Vector3<S> tempRac = Ta->linear().col(code1);
1279  m11 = Tb->linear().col(a1).dot(tempRac);
1280  m12 = Tb->linear().col(a2).dot(tempRac);
1281  tempRac = Ta->linear().col(code2);
1282  m21 = Tb->linear().col(a1).dot(tempRac);
1283  m22 = Tb->linear().col(a2).dot(tempRac);
1284 
1285  S k1 = m11 * (*Sb)[a1];
1286  S k2 = m21 * (*Sb)[a1];
1287  S k3 = m12 * (*Sb)[a2];
1288  S k4 = m22 * (*Sb)[a2];
1289  quad[0] = c1 - k1 - k3;
1290  quad[1] = c2 - k2 - k4;
1291  quad[2] = c1 - k1 + k3;
1292  quad[3] = c2 - k2 + k4;
1293  quad[4] = c1 + k1 + k3;
1294  quad[5] = c2 + k2 + k4;
1295  quad[6] = c1 + k1 - k3;
1296  quad[7] = c2 + k2 - k4;
1297 
1298  // find the size of the reference face
1299  S rect[2];
1300  rect[0] = (*Sa)[code1];
1301  rect[1] = (*Sa)[code2];
1302 
1303  // intersect the incident and reference faces
1304  S ret[16];
1305  int n_intersect = intersectRectQuad2(rect, quad, ret);
1306  if(n_intersect < 1) { *return_code = code; return 0; } // this should never happen
1307 
1308  // convert the intersection points into reference-face coordinates,
1309  // and compute the contact position and depth for each point. only keep
1310  // those points that have a positive (penetrating) depth. delete points in
1311  // the 'ret' array as necessary so that 'point' and 'ret' correspond.
1312  Vector3<S> points[8]; // penetrating contact points
1313  S dep[8]; // depths for those points
1314  S det1 = 1.f/(m11*m22 - m12*m21);
1315  m11 *= det1;
1316  m12 *= det1;
1317  m21 *= det1;
1318  m22 *= det1;
1319  int cnum = 0; // number of penetrating contact points found
1320  for(int j = 0; j < n_intersect; ++j)
1321  {
1322  S k1 = m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
1323  S k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
1324  points[cnum] = center + Tb->linear().col(a1) * k1 + Tb->linear().col(a2) * k2;
1325  dep[cnum] = (*Sa)[codeN] - normal2.dot(points[cnum]);
1326  if(dep[cnum] >= 0)
1327  {
1328  ret[cnum*2] = ret[j*2];
1329  ret[cnum*2+1] = ret[j*2+1];
1330  cnum++;
1331  }
1332  }
1333  if(cnum < 1) { *return_code = code; return 0; } // this should never happen
1334 
1335  // we can't generate more contacts than we actually have
1336  if(maxc > cnum) maxc = cnum;
1337  if(maxc < 1) maxc = 1;
1338 
1339  if(cnum <= maxc)
1340  {
1341  if(code<4)
1342  {
1343  // we have less contacts than we need, so we use them all
1344  for(int j = 0; j < cnum; ++j)
1345  {
1346  Vector3<S> pointInWorld = points[j] + Ta->translation();
1347  contacts.emplace_back(normal, pointInWorld, -dep[j]);
1348  }
1349  }
1350  else
1351  {
1352  // we have less contacts than we need, so we use them all
1353  for(int j = 0; j < cnum; ++j)
1354  {
1355  Vector3<S> pointInWorld = points[j] + Ta->translation() - normal * dep[j];
1356  contacts.emplace_back(normal, pointInWorld, -dep[j]);
1357  }
1358  }
1359  }
1360  else
1361  {
1362  // we have more contacts than are wanted, some of them must be culled.
1363  // find the deepest point, it is always the first contact.
1364  int i1 = 0;
1365  S maxdepth = dep[0];
1366  for(int i = 1; i < cnum; ++i)
1367  {
1368  if(dep[i] > maxdepth)
1369  {
1370  maxdepth = dep[i];
1371  i1 = i;
1372  }
1373  }
1374 
1375  int iret[8];
1376  cullPoints2(cnum, ret, maxc, i1, iret);
1377 
1378  for(int j = 0; j < maxc; ++j)
1379  {
1380  Vector3<S> posInWorld = points[iret[j]] + Ta->translation();
1381  if(code < 4)
1382  contacts.emplace_back(normal, posInWorld, -dep[iret[j]]);
1383  else
1384  contacts.emplace_back(normal, posInWorld - normal * dep[iret[j]], -dep[iret[j]]);
1385  }
1386  cnum = maxc;
1387  }
1388 
1389  *return_code = code;
1390  return cnum;
1391 }
1392 
1393 //==============================================================================
1394 template <typename S>
1395 bool boxBoxIntersect(const Box<S>& s1, const Transform3<S>& tf1,
1396  const Box<S>& s2, const Transform3<S>& tf2,
1397  std::vector<ContactPoint<S>>* contacts_)
1398 {
1399  std::vector<ContactPoint<S>> contacts;
1400  int return_code;
1401  Vector3<S> normal;
1402  S depth;
1403  /* int cnum = */ boxBox2(s1.side, tf1,
1404  s2.side, tf2,
1405  normal, &depth, &return_code,
1406  4, contacts);
1407 
1408  if(contacts_)
1409  *contacts_ = contacts;
1410 
1411  return return_code != 0;
1412 }
1413 
1414 } // namespace detail
1415 } // namespace fcl
1416 
1417 #endif
Main namespace.
Definition: broadphase_bruteforce-inl.h:45
static constexpr S pi()
The mathematical constant pi.
Definition: constants.h:49