38 #ifndef FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H
39 #define FCL_NARROWPHASE_DETAIL_GJKLIBCCD_INL_H
45 #include <unordered_map>
46 #include <unordered_set>
59 class FCL_EXPORT GJKInitializer<double, Cylinder<double>>;
63 class FCL_EXPORT GJKInitializer<double, Sphere<double>>;
67 class FCL_EXPORT GJKInitializer<double, Ellipsoid<double>>;
71 class FCL_EXPORT GJKInitializer<double, Box<double>>;
75 class FCL_EXPORT GJKInitializer<double, Capsule<double>>;
79 class FCL_EXPORT GJKInitializer<double, Cone<double>>;
83 class FCL_EXPORT GJKInitializer<double, Convex<double>>;
102 ccd_support_fn supp1,
105 ccd_support_fn supp2,
107 unsigned int max_iterations,
110 double* penetration_depth,
117 ccd_support_fn supp1,
119 ccd_support_fn supp2,
120 unsigned int max_iterations,
129 ccd_support_fn supp1,
131 ccd_support_fn supp2,
132 unsigned int max_iterations,
174 template <
typename S>
186 namespace libccd_extension
191 ccd_vec3_t *best_witness)
199 for (i = 0; i < 3; i++){
200 newdist = ccdVec3PointTriDist2(ccd_vec3_origin,
205 newdist = CCD_SQRT(newdist);
211 ccdVec3Copy(best_witness, &witness);
223 _ccd_inline
void tripleCross(
const ccd_vec3_t *a,
const ccd_vec3_t *b,
224 const ccd_vec3_t *c, ccd_vec3_t *d)
227 ccdVec3Cross(&e, a, b);
228 ccdVec3Cross(d, &e, c);
335 assert(p_OA.dot(p_OB) <= p_OB.squaredNorm() * eps &&
"A is not in region 1");
355 if (plane_normal.squaredNorm() <
356 p_AB.squaredNorm() * p_OB.squaredNorm() * eps * eps) {
369 ccdVec3Set(dir, new_dir(0), new_dir(1), new_dir(2));
391 ccd_vec3_t AO, AB, AC, ABC, tmp;
404 ccd_vec3_t origin_projection_unused;
406 const ccd_real_t dist_squared = ccdVec3PointTriDist2(
407 ccd_vec3_origin, &A->
v, &B->
v, &C->
v, &origin_projection_unused);
418 if (ccdVec3Eq(&A->
v, &B->
v) || ccdVec3Eq(&A->
v, &C->
v)){
424 ccdVec3Copy(&AO, &A->
v);
425 ccdVec3Scale(&AO, -CCD_ONE);
428 ccdVec3Sub2(&AB, &B->
v, &A->
v);
429 ccdVec3Sub2(&AC, &C->
v, &A->
v);
430 ccdVec3Cross(&ABC, &AB, &AC);
432 ccdVec3Cross(&tmp, &ABC, &AC);
433 dot = ccdVec3Dot(&tmp, &AO);
434 if (ccdIsZero(dot) || dot > CCD_ZERO){
435 dot = ccdVec3Dot(&AC, &AO);
436 if (ccdIsZero(dot) || dot > CCD_ZERO){
443 dot = ccdVec3Dot(&AB, &AO);
444 if (ccdIsZero(dot) || dot > CCD_ZERO){
452 ccdVec3Copy(dir, &AO);
456 ccdVec3Cross(&tmp, &AB, &ABC);
457 dot = ccdVec3Dot(&tmp, &AO);
458 if (ccdIsZero(dot) || dot > CCD_ZERO){
459 goto ccd_do_simplex3_45;
461 dot = ccdVec3Dot(&ABC, &AO);
462 if (ccdIsZero(dot) || dot > CCD_ZERO){
463 ccdVec3Copy(dir, &ABC);
470 ccdVec3Copy(dir, &ABC);
471 ccdVec3Scale(dir, -CCD_ONE);
482 ccd_vec3_t AO, AB, AC, AD, ABC, ACD, ADB;
483 int B_on_ACD, C_on_ADB, D_on_ABC;
484 int AB_O, AC_O, AD_O;
500 ccd_vec3_t point_projection_on_triangle_unused;
501 ccd_real_t dist_squared = ccdVec3PointTriDist2(
502 &A->
v, &B->
v, &C->
v, &D->
v, &point_projection_on_triangle_unused);
509 dist_squared = ccdVec3PointTriDist2(ccd_vec3_origin, &A->
v, &B->
v, &C->
v,
510 &point_projection_on_triangle_unused);
512 dist_squared = ccdVec3PointTriDist2(ccd_vec3_origin, &A->
v, &C->
v, &D->
v,
513 &point_projection_on_triangle_unused);
515 dist_squared = ccdVec3PointTriDist2(ccd_vec3_origin, &A->
v, &B->
v, &D->
v,
516 &point_projection_on_triangle_unused);
518 dist_squared = ccdVec3PointTriDist2(ccd_vec3_origin, &B->
v, &C->
v, &D->
v,
519 &point_projection_on_triangle_unused);
523 ccdVec3Copy(&AO, &A->
v);
524 ccdVec3Scale(&AO, -CCD_ONE);
525 ccdVec3Sub2(&AB, &B->
v, &A->
v);
526 ccdVec3Sub2(&AC, &C->
v, &A->
v);
527 ccdVec3Sub2(&AD, &D->
v, &A->
v);
528 ccdVec3Cross(&ABC, &AB, &AC);
529 ccdVec3Cross(&ACD, &AC, &AD);
530 ccdVec3Cross(&ADB, &AD, &AB);
534 B_on_ACD = ccdSign(ccdVec3Dot(&ACD, &AB));
535 C_on_ADB = ccdSign(ccdVec3Dot(&ADB, &AC));
536 D_on_ABC = ccdSign(ccdVec3Dot(&ABC, &AD));
540 AB_O = ccdSign(ccdVec3Dot(&ACD, &AO)) == B_on_ACD;
541 AC_O = ccdSign(ccdVec3Dot(&ADB, &AO)) == C_on_ADB;
542 AD_O = ccdSign(ccdVec3Dot(&ABC, &AO)) == D_on_ABC;
544 if (AB_O && AC_O && AD_O){
595 ccd_vec3_t ab, ac, dir;
614 for (i = 0; i < ccd_points_on_sphere_len; i++){
616 if (!ccdVec3Eq(&a->
v, &supp[0].
v) && !ccdVec3Eq(&b->
v, &supp[0].
v)){
622 goto simplexToPolytope2_touching_contact;
625 ccdVec3Copy(&dir, &supp[0].v);
626 ccdVec3Scale(&dir, -CCD_ONE);
628 if (ccdVec3Eq(&a->
v, &supp[1].
v) || ccdVec3Eq(&b->
v, &supp[1].
v))
629 goto simplexToPolytope2_touching_contact;
632 ccdVec3Sub2(&ab, &supp[0].v, &a->
v);
633 ccdVec3Sub2(&ac, &supp[1].v, &a->
v);
634 ccdVec3Cross(&dir, &ab, &ac);
636 if (ccdVec3Eq(&a->
v, &supp[2].
v) || ccdVec3Eq(&b->
v, &supp[2].
v))
637 goto simplexToPolytope2_touching_contact;
640 ccdVec3Scale(&dir, -CCD_ONE);
642 if (ccdVec3Eq(&a->
v, &supp[3].
v) || ccdVec3Eq(&b->
v, &supp[3].
v))
643 goto simplexToPolytope2_touching_contact;
645 goto simplexToPolytope2_not_touching_contact;
646 simplexToPolytope2_touching_contact:
650 if (*nearest == NULL)
655 simplexToPolytope2_not_touching_contact:
740 assert(simplex->
last == 2);
743 ccd_vec3_t ab, ac, dir;
756 ccdVec3Sub2(&ab, &b->
v, &a->
v);
757 ccdVec3Sub2(&ac, &c->
v, &a->
v);
758 ccdVec3Cross(&dir, &ab, &ac);
760 ccd_vec3_t point_projection_on_triangle_unused;
761 const ccd_real_t dist_squared = ccdVec3PointTriDist2(
762 &d.
v, &a->
v, &b->
v, &c->
v, &point_projection_on_triangle_unused);
765 ccdVec3Scale(&dir, -CCD_ONE);
767 const ccd_real_t dist_squared_opposite = ccdVec3PointTriDist2(
768 &d2.
v, &a->
v, &b->
v, &c->
v, &point_projection_on_triangle_unused);
772 if (ccdIsZero(dist_squared) || ccdIsZero(dist_squared_opposite)) {
780 if (*nearest == NULL)
return -2;
788 auto FormTetrahedron = [polytope, a, b, c, &v,
818 if (std::abs(dist_squared) > std::abs(dist_squared_opposite)) {
819 return FormTetrahedron(d);
821 return FormTetrahedron(d2);
831 bool use_polytope3{
false};
847 ccd_real_t dist_squared =
848 ccdVec3PointTriDist2(ccd_vec3_origin, &a->
v, &b->
v, &c->
v, NULL);
850 use_polytope3 =
true;
852 if (!use_polytope3) {
854 ccdVec3PointTriDist2(ccd_vec3_origin, &a->
v, &c->
v, &d->
v, NULL);
856 use_polytope3 =
true;
861 if (!use_polytope3) {
863 ccdVec3PointTriDist2(ccd_vec3_origin, &a->
v, &b->
v, &d->
v, NULL);
865 use_polytope3 =
true;
869 if (!use_polytope3) {
871 ccdVec3PointTriDist2(ccd_vec3_origin, &b->
v, &c->
v, &d->
v, NULL);
873 use_polytope3 =
true;
886 for (i = 0; i < 4; i++) {
928 for (
int i = 0; i < 3; ++i) {
930 max({ccd_real_t{1}, abs(p.v[i]), abs(q.v[i])}) * eps;
931 const ccd_real_t delta = abs(p.v[i] - q.v[i]);
944 const ccd_vec3_t& c) {
957 ccd_vec3_t AB, AC, n;
958 ccdVec3Sub2(&AB, &b, &a);
959 ccdVec3Sub2(&AC, &c, &a);
960 ccdVec3Normalize(&AB);
961 ccdVec3Normalize(&AC);
962 ccdVec3Cross(&n, &AB, &AC);
965 if (ccdVec3Len2(&n) < eps * eps)
return true;
990 const ccd_vec3_t& test_v = face->
edge[1]->
vertex[0]->
v.
v;
995 "Cannot compute face normal for a degenerate (zero-area) triangle");
1009 ccdVec3Cross(&dir, &e1, &e2);
1010 const ccd_real_t dir_norm = std::sqrt(ccdVec3Len2(&dir));
1011 ccd_vec3_t unit_dir = dir;
1012 ccdVec3Scale(&unit_dir, 1.0 / dir_norm);
1031 const ccd_real_t dist_tol = 0.01;
1035 const ccd_real_t origin_distance_to_plane =
1036 ccdVec3Dot(&unit_dir, &(face->
edge[0]->
vertex[0]->
v.
v));
1037 if (origin_distance_to_plane < -dist_tol) {
1041 ccdVec3Scale(&dir, ccd_real_t(-1));
1042 }
else if (-dist_tol <= origin_distance_to_plane &&
1043 origin_distance_to_plane <= dist_tol) {
1046 ccd_real_t max_distance_to_plane = -CCD_REAL_MAX;
1047 ccd_real_t min_distance_to_plane = CCD_REAL_MAX;
1057 const ccd_real_t distance_to_plane =
1058 ccdVec3Dot(&unit_dir, &(v->
v.
v)) - origin_distance_to_plane;
1059 if (distance_to_plane > dist_tol) {
1063 ccdVec3Scale(&dir, ccd_real_t(-1));
1065 }
else if (distance_to_plane < -dist_tol) {
1070 max_distance_to_plane =
1071 std::max(max_distance_to_plane, distance_to_plane);
1072 min_distance_to_plane =
1073 std::min(min_distance_to_plane, distance_to_plane);
1080 if (max_distance_to_plane > std::abs(min_distance_to_plane)) {
1081 ccdVec3Scale(&dir, ccd_real_t(-1));
1098 return ccdVec3Dot(&n, &r_VP) > 0;
1117 const std::unordered_set<ccd_pt_edge_t*>& border_edges,
1118 const std::unordered_set<ccd_pt_face_t*>& visible_faces,
1119 const std::unordered_set<ccd_pt_edge_t*>& internal_edges) {
1124 bool has_edge_internal =
false;
1125 for (
int i = 0; i < 3; ++i) {
1128 if (internal_edges.count(f->
edge[i]) > 0) {
1129 has_edge_internal =
true;
1133 if (has_edge_internal) {
1134 if (visible_faces.count(f) == 0) {
1141 if (visible_faces.count(e->
faces[0]) > 0 &&
1142 visible_faces.count(e->
faces[1]) > 0) {
1143 if (internal_edges.count(e) == 0) {
1146 }
else if (visible_faces.count(e->
faces[0]) +
1147 visible_faces.count(e->
faces[1]) ==
1149 if (border_edges.count(e) == 0) {
1154 for (
const auto b : border_edges) {
1155 if (internal_edges.count(b) > 0) {
1171 std::unordered_set<ccd_pt_edge_t*>* border_edges,
1172 std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1173 border_edges->insert(edge);
1174 if (internal_edges->count(edge) > 0) {
1176 "An edge is being classified as border that has already been "
1177 "classifed as internal");
1189 std::unordered_set<ccd_pt_edge_t*>* border_edges,
1190 std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1191 internal_edges->insert(edge);
1192 if (border_edges->count(edge) > 0) {
1194 "An edge is being classified as internal that has already been "
1195 "classified as border");
1214 const ccd_vec3_t& query_point,
1215 std::unordered_set<ccd_pt_edge_t*>* border_edges,
1216 std::unordered_set<ccd_pt_face_t*>* visible_faces,
1217 std::unordered_set<ccd_pt_face_t*>* hidden_faces,
1218 std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1222 assert(g !=
nullptr);
1224 bool is_visible = visible_faces->count(g) > 0;
1225 bool is_hidden = hidden_faces->count(g) > 0;
1226 assert(!(is_visible && is_hidden));
1263 visible_faces->insert(g);
1265 for (
int i = 0; i < 3; ++i) {
1266 if (g->
edge[i] != edge) {
1269 visible_faces, hidden_faces,
1277 hidden_faces->insert(g);
1317 const ccd_vec3_t& query_point,
1318 std::unordered_set<ccd_pt_edge_t*>* border_edges,
1319 std::unordered_set<ccd_pt_face_t*>* visible_faces,
1320 std::unordered_set<ccd_pt_edge_t*>* internal_edges) {
1321 assert(border_edges);
1322 assert(visible_faces);
1323 assert(internal_edges);
1324 assert(border_edges->empty());
1325 assert(visible_faces->empty());
1326 assert(internal_edges->empty());
1328 std::unordered_set<ccd_pt_face_t*> hidden_faces;
1329 visible_faces->insert(&f);
1330 for (
int edge_index = 0; edge_index < 3; ++edge_index) {
1332 border_edges, visible_faces, &hidden_faces,
1338 polytope, *border_edges, *visible_faces, *internal_edges)) {
1340 "The visible patch failed its sanity check");
1395 "The visible feature is a vertex. This should already have been "
1396 "identified as a touching contact");
1411 "Both the nearest point and the new vertex are on an edge, thus the "
1412 "nearest distance should be 0. This is touching contact, and should "
1413 "already have been identified");
1417 std::unordered_set<ccd_pt_face_t*> visible_faces;
1418 std::unordered_set<ccd_pt_edge_t*> internal_edges;
1419 std::unordered_set<ccd_pt_edge_t*> border_edges;
1421 &visible_faces, &internal_edges);
1428 for (
const auto& f : visible_faces) {
1433 for (
const auto& e : internal_edges) {
1456 std::unordered_map<ccd_pt_vertex_t*, ccd_pt_edge_t*> map_vertex_to_new_edge;
1457 for (
const auto& border_edge : border_edges) {
1460 for (
int i = 0; i < 2; ++i) {
1461 auto it = map_vertex_to_new_edge.find(border_edge->vertex[i]);
1462 if (it == map_vertex_to_new_edge.end()) {
1464 e[i] =
ccdPtAddEdge(polytope, new_vertex, border_edge->vertex[i]);
1465 map_vertex_to_new_edge.emplace_hint(it, border_edge->vertex[i],
1498 if (ccdIsZero(nearest_feature->dist)) {
1500 switch (nearest_feature->type) {
1503 "The nearest point to the origin is a vertex of the polytope. This "
1504 "should be identified as a touching contact");
1528 ccdVec3Copy(&dir, &(nearest_feature->witness));
1530 ccdVec3Normalize(&dir);
1554 const void*
obj2,
const ccd_t* ccd,
1556 ccd_vec3_t *a, *b, *c;
1566 const ccd_real_t dist = ccdVec3Dot(&out->
v, &dir);
1572 if (dist - std::sqrt(el->dist) < ccd->epa_tolerance)
return -1;
1574 ccd_real_t dist_squared{};
1580 dist_squared = ccdVec3PointSegmentDist2(&out->
v, a, b, NULL);
1586 ccd_vec3_t point_projection_on_triangle_unused;
1587 dist_squared = ccdVec3PointTriDist2(&out->
v, a, b, c,
1588 &point_projection_on_triangle_unused);
1591 if (std::sqrt(dist_squared) < ccd->epa_tolerance)
return -1;
1600 unsigned long iterations;
1616 ccdVec3Copy(&dir, &last.
v);
1617 ccdVec3Scale(&dir, -CCD_ONE);
1620 for (iterations = 0UL; iterations < ccd->max_iterations; ++iterations) {
1627 if (ccdVec3Dot(&last.
v, &dir) < CCD_ZERO){
1636 do_simplex_res =
doSimplex(simplex, &dir);
1637 if (do_simplex_res == 1){
1639 }
else if (do_simplex_res == -1){
1643 if (ccdIsZero(ccdVec3Len2(&dir))){
1688 std::array<ccd_vec3_t, 2> face_normals;
1689 std::array<double, 2> origin_to_face_distance;
1694 const ccd_real_t v0_dist =
1695 std::sqrt(ccdVec3Len2(&nearest_edge->
vertex[0]->
v.
v));
1696 const ccd_real_t plane_threshold =
1697 kEps *
std::max(
static_cast<ccd_real_t
>(1.0), v0_dist);
1699 for (
int i = 0; i < 2; ++i) {
1702 ccdVec3Normalize(&face_normals[i]);
1705 origin_to_face_distance[i] =
1706 -ccdVec3Dot(&face_normals[i], &nearest_edge->
vertex[0]->
v.
v);
1718 if (origin_to_face_distance[i] > plane_threshold) {
1720 "The origin is outside of the polytope. This should already have "
1721 "been identified as separating.");
1728 const bool is_edge_closest_feature = nearest_edge->dist <
kEps *
kEps;
1730 if (!is_edge_closest_feature) {
1738 const int closest_face =
1739 origin_to_face_distance[0] < origin_to_face_distance[1] ? 1 : 0;
1743 polytope->
nearest_dist = pow(origin_to_face_distance[closest_face], 2);
1763 }
else if (size == 3) {
1774 }
else if (ret == -2){
1810 if (p1) *p1 = q->
v1;
1811 if (p2) *p2 = q->
v2;
1819 ccd_vec3_t *p1, ccd_vec3_t *p2,
1827 ccdVec3Sub2(&AB, &(b->
v), &(a->
v));
1840 ccd_real_t abs_AB_x{std::abs(ccdVec3X(&AB))};
1841 ccd_real_t abs_AB_y{std::abs(ccdVec3Y(&AB))};
1842 ccd_real_t abs_AB_z{std::abs(ccdVec3Z(&AB))};
1844 ccd_real_t A_i, AB_i, p_i;
1845 if (abs_AB_x >= abs_AB_y && abs_AB_x >= abs_AB_z) {
1846 A_i = ccdVec3X(&(a->
v));
1847 AB_i = ccdVec3X(&AB);
1849 }
else if (abs_AB_y >= abs_AB_z) {
1850 A_i = ccdVec3Y(&(a->
v));
1851 AB_i = ccdVec3Y(&AB);
1854 A_i = ccdVec3Z(&(a->
v));
1855 AB_i = ccdVec3Z(&AB);
1865 auto calc_p = [](ccd_vec3_t *p_a, ccd_vec3_t *p_b, ccd_vec3_t *p,
1868 ccdVec3Sub2(&sAB, p_b, p_a);
1869 ccdVec3Scale(&sAB, s);
1870 ccdVec3Copy(p, p_a);
1871 ccdVec3Add(p, &sAB);
1877 ccd_real_t s = (p_i - A_i) / AB_i;
1881 calc_p(&(a->
v1), &(b->
v1), p1, s);
1885 calc_p(&(a->
v2), &(b->
v2), p2, s);
1895 ccd_vec3_t *p2, ccd_vec3_t *p) {
1897 assert(simplex_size <= 3);
1898 if (simplex_size == 1)
1902 else if (simplex_size == 2)
1909 simplex->
ps[2].
v)) {
1912 int a_index, b_index;
1913 ccd_vec3_t AB, AC, BC;
1914 ccdVec3Sub2(&AB, &(simplex->
ps[1].
v), &(simplex->
ps[0].
v));
1915 ccdVec3Sub2(&AC, &(simplex->
ps[2].
v), &(simplex->
ps[0].
v));
1916 ccdVec3Sub2(&BC, &(simplex->
ps[2].
v), &(simplex->
ps[1].
v));
1917 ccd_real_t AB_len2 = ccdVec3Len2(&AB);
1918 ccd_real_t AC_len2 = ccdVec3Len2(&AC);
1919 ccd_real_t BC_len2 = ccdVec3Len2(&BC);
1920 if (AB_len2 >= AC_len2 && AB_len2 >= BC_len2) {
1923 }
else if (AC_len2 >= AB_len2 && AC_len2 >= BC_len2) {
1931 &simplex->
ps[b_index], p1, p2, p);
1971 ccd_vec3_t r_AB, r_AC, n;
1972 ccdVec3Sub2(&r_AB, &(simplex->
ps[1].
v), &(simplex->
ps[0].
v));
1973 ccdVec3Sub2(&r_AC, &(simplex->
ps[2].
v), &(simplex->
ps[0].
v));
1974 ccdVec3Cross(&n, &r_AB, &r_AC);
1975 ccd_real_t norm_squared_n{ccdVec3Len2(&n)};
1979 ccdVec3Sub2(&r_Ap, p, &(simplex->
ps[0].
v));
1982 ccd_vec3_t r_Ap_cross_r_AC, r_AB_cross_r_Ap;
1983 ccdVec3Cross(&r_Ap_cross_r_AC, &r_Ap, &r_AC);
1984 ccdVec3Cross(&r_AB_cross_r_Ap, &r_AB, &r_Ap);
1987 ccd_real_t beta{ccdVec3Dot(&n, &r_Ap_cross_r_AC) / norm_squared_n};
1988 ccd_real_t gamma{ccdVec3Dot(&n, &r_AB_cross_r_Ap) / norm_squared_n};
1992 auto interpolate = [&beta, &gamma](
const ccd_vec3_t& r_WA,
1993 const ccd_vec3_t& r_WB,
1994 const ccd_vec3_t& r_WC,
1997 ccdVec3Copy(r_WP, &r_WA);
1999 ccd_vec3_t beta_r_AB;
2000 ccdVec3Sub2(&beta_r_AB, &r_WB, &r_WA);
2001 ccdVec3Scale(&beta_r_AB, beta);
2002 ccdVec3Add(r_WP, &beta_r_AB);
2004 ccd_vec3_t gamma_r_AC;
2005 ccdVec3Sub2(&gamma_r_AC, &r_WC, &r_WA);
2006 ccdVec3Scale(&gamma_r_AC, gamma);
2007 ccdVec3Add(r_WP, &gamma_r_AC);
2011 interpolate(simplex->
ps[0].
v1, simplex->
ps[1].
v1, simplex->
ps[2].
v1, p1);
2015 interpolate(simplex->
ps[0].
v2, simplex->
ps[1].
v2, simplex->
ps[2].
v2, p2);
2038 ccd_vec3_t* p1, ccd_vec3_t* p2)
2040 ccd_real_t last_dist = CCD_REAL_MAX;
2042 for (
unsigned long iterations = 0UL; iterations < ccd->max_iterations;
2044 ccd_vec3_t closest_p;
2056 dist = CCD_SQRT(dist);
2060 dist = ccdVec3PointSegmentDist2(ccd_vec3_origin,
2064 dist = CCD_SQRT(dist);
2068 dist = ccdVec3PointTriDist2(ccd_vec3_origin,
2073 dist = CCD_SQRT(dist);
2081 if ((last_dist - dist) < ccd->dist_tolerance)
2089 ccdVec3Copy(&dir, &closest_p);
2090 ccdVec3Scale(&dir, -CCD_ONE);
2091 ccdVec3Normalize(&dir);
2103 dist = ccdVec3Len2(&last.
v);
2104 dist = CCD_SQRT(dist);
2105 if (CCD_FABS(last_dist - dist) < ccd->dist_tolerance)
2115 return -CCD_REAL(1.);
2138 ccdVec3Copy(p1, &v->
v.
v1);
2139 ccdVec3Copy(p2, &v->
v.
v2);
2160 for (
int i = 0; i < 2; ++i) {
2169 throw std::logic_error(
2170 "FCL penEPAPosClosest(): Unsupported feature type. The closest point "
2171 "should be either a vertex, on an edge, or on a face.");
2180 ccdVec3Copy(&p, &(nearest->witness));
2187 const ccd_t* ccd, ccd_vec3_t* p1,
2200 if (ret == 0 && nearest)
2202 depth = -CCD_SQRT(nearest->dist);
2204 ccd_vec3_t pos1, pos2;
2250 const ccd_t *ccd, ccd_vec3_t* p1,
2264 template <
typename S>
2272 ccdVec3Set(&o->
pos, T[0], T[1], T[2]);
2273 ccdQuatSet(&o->
rot, q.x(), q.y(), q.z(), q.w());
2277 template <
typename S>
2281 box->
dim[0] = s.
side[0] / 2.0;
2282 box->
dim[1] = s.
side[1] / 2.0;
2283 box->
dim[2] = s.
side[2] / 2.0;
2286 template <
typename S>
2295 template <
typename S>
2304 template <
typename S>
2313 template <
typename S>
2321 template <
typename S>
2331 template <
typename S>
2348 auto sign = [](ccd_real_t x) -> ccd_real_t {
2349 return x >= 0 ? ccd_real_t(1.0) : ccd_real_t(-1.0);
2353 ccdVec3Copy(&dir,
dir_);
2354 ccdQuatRotVec(&dir, &o->
rot_inv);
2355 ccdVec3Set(v, sign(ccdVec3X(&dir)) * o->
dim[0],
2356 sign(ccdVec3Y(&dir)) * o->
dim[1],
2357 sign(ccdVec3Z(&dir)) * o->
dim[2]);
2358 ccdQuatRotVec(v, &o->
rot);
2359 ccdVec3Add(v, &o->
pos);
2366 ccd_vec3_t dir, pos1, pos2;
2368 ccdVec3Copy(&dir,
dir_);
2369 ccdQuatRotVec(&dir, &o->
rot_inv);
2371 ccdVec3Set(&pos1, CCD_ZERO, CCD_ZERO, o->
height);
2372 ccdVec3Set(&pos2, CCD_ZERO, CCD_ZERO, -o->
height);
2374 ccdVec3Copy(v, &dir);
2375 ccdVec3Normalize (v);
2376 ccdVec3Scale(v, o->
radius);
2377 ccdVec3Add(&pos1, v);
2378 ccdVec3Add(&pos2, v);
2380 if (ccdVec3Z (&dir) > 0)
2381 ccdVec3Copy(v, &pos1);
2383 ccdVec3Copy(v, &pos2);
2386 ccdQuatRotVec(v, &o->
rot);
2387 ccdVec3Add(v, &o->
pos);
2397 ccdVec3Copy(&dir,
dir_);
2398 ccdQuatRotVec(&dir, &cyl->
rot_inv);
2400 zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1];
2401 zdist = sqrt(zdist);
2402 if (ccdIsZero(zdist))
2403 ccdVec3Set(v, 0., 0., ccdSign(ccdVec3Z(&dir)) * cyl->
height);
2406 rad = cyl->
radius / zdist;
2408 ccdVec3Set(v, rad * ccdVec3X(&dir),
2409 rad * ccdVec3Y(&dir),
2410 ccdSign(ccdVec3Z(&dir)) * cyl->
height);
2414 ccdQuatRotVec(v, &cyl->
rot);
2415 ccdVec3Add(v, &cyl->
pos);
2424 ccdVec3Copy(&dir,
dir_);
2425 ccdQuatRotVec(&dir, &cone->
rot_inv);
2427 double zdist, len, rad;
2428 zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1];
2429 len = zdist + dir.v[2] * dir.v[2];
2430 zdist = sqrt(zdist);
2435 if (dir.v[2] > len * sin_a)
2436 ccdVec3Set(v, 0., 0., cone->
height);
2439 rad = cone->
radius / zdist;
2440 ccdVec3Set(v, rad * ccdVec3X(&dir), rad * ccdVec3Y(&dir), -cone->
height);
2443 ccdVec3Set(v, 0, 0, -cone->
height);
2446 ccdQuatRotVec(v, &cone->
rot);
2447 ccdVec3Add(v, &cone->
pos);
2456 ccdVec3Copy(&dir,
dir_);
2457 ccdQuatRotVec(&dir, &s->
rot_inv);
2459 ccdVec3Copy(v, &dir);
2460 ccdVec3Scale(v, s->
radius);
2461 ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Len2(&dir)));
2464 ccdQuatRotVec(v, &s->
rot);
2465 ccdVec3Add(v, &s->
pos);
2474 ccdVec3Copy(&dir,
dir_);
2475 ccdQuatRotVec(&dir, &s->
rot_inv);
2482 v->v[0] = abc2.v[0] * dir.v[0];
2483 v->v[1] = abc2.v[1] * dir.v[1];
2484 v->v[2] = abc2.v[2] * dir.v[2];
2486 ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Dot(v, &dir)));
2489 ccdQuatRotVec(v, &s->
rot);
2490 ccdVec3Add(v, &s->
pos);
2493 template <
typename S>
2502 ccdVec3Copy(&dir,
dir_);
2503 ccdQuatRotVec(&dir, &c->rot_inv);
2507 Vector3<S> dir_C{S(dir.v[0]), S(dir.v[1]), S(dir.v[2])};
2510 const Vector3<S>& p_CE = c->convex->findExtremeVertex(dir_C);
2516 ccdQuatRotVec(v, &c->rot);
2517 ccdVec3Add(v, &c->pos);
2525 ccd_real_t maxdot, dot;
2528 ccdVec3Copy(&dir,
dir_);
2529 ccdQuatRotVec(&dir, &tri->
rot_inv);
2531 maxdot = -CCD_REAL_MAX;
2533 for (i = 0; i < 3; ++i)
2535 ccdVec3Set(&p, tri->
p[i].v[0] - tri->
c.v[0], tri->
p[i].v[1] - tri->
c.v[1],
2536 tri->
p[i].v[2] - tri->
c.v[2]);
2537 dot = ccdVec3Dot(&dir, &p);
2540 ccdVec3Copy(v, &tri->
p[i]);
2546 ccdQuatRotVec(v, &tri->
rot);
2547 ccdVec3Add(v, &tri->
pos);
2553 ccdVec3Copy(c, &o->
pos);
2556 template <
typename S>
2561 ccdVec3Set(c, p[0], p[1], p[2]);
2562 ccdQuatRotVec(c, &o->rot);
2563 ccdVec3Add(c, &o->pos);
2569 ccdVec3Copy(c, &o->
c);
2570 ccdQuatRotVec(c, &o->
rot);
2571 ccdVec3Add(c, &o->
pos);
2574 template <
typename S>
2576 void*
obj2, ccd_support_fn supp2, ccd_center_fn cen2,
2577 unsigned int max_iterations, S
tolerance,
2578 Vector3<S>* contact_points, S* penetration_depth,
2584 ccd_vec3_t dir, pos;
2588 ccd.support1 = supp1;
2589 ccd.support2 = supp2;
2592 ccd.max_iterations = max_iterations;
2595 if (!contact_points)
2597 return ccdMPRIntersect(
obj1,
obj2, &ccd);
2603 res = ccdMPRPenetration(
obj1,
obj2, &ccd, &depth, &dir, &pos);
2606 *contact_points << ccdVec3X(&pos), ccdVec3Y(&pos), ccdVec3Z(&pos);
2607 *penetration_depth = depth;
2608 *normal << ccdVec3X(&dir), ccdVec3Y(&dir), ccdVec3Z(&dir);
2621 using DistanceFn = std::function<ccd_real_t (
2622 const void*,
const void*,
const ccd_t*, ccd_vec3_t*, ccd_vec3_t*)>;
2646 template <
typename S>
2648 ccd_support_fn supp2,
unsigned int max_iterations,
2654 ccd.support1 = supp1;
2655 ccd.support2 = supp2;
2657 ccd.max_iterations = max_iterations;
2661 ccd_vec3_t p1_, p2_;
2667 ccdVec3Set(&p1_, 0.0, 0.0, 0.0);
2668 ccdVec3Set(&p2_, 0.0, 0.0, 0.0);
2669 dist = distance_func(
obj1,
obj2, &ccd, &p1_, &p2_);
2670 if (p1) *p1 << ccdVec3X(&p1_), ccdVec3Y(&p1_), ccdVec3Z(&p1_);
2671 if (p2) *p2 << ccdVec3X(&p2_), ccdVec3Y(&p2_), ccdVec3Z(&p2_);
2672 if (res) *res = dist;
2679 template <
typename S>
2681 void*
obj2, ccd_support_fn supp2,
2682 unsigned int max_iterations, S
tolerance,
2702 template <
typename S>
2704 void*
obj2, ccd_support_fn supp2,
2705 unsigned int max_iterations,
2712 template <
typename S>
2718 template <
typename S>
2724 template <
typename S>
2733 template <
typename S>
2740 template <
typename S>
2746 template <
typename S>
2752 template <
typename S>
2761 template <
typename S>
2768 template <
typename S>
2774 template <
typename S>
2780 template <
typename S>
2789 template <
typename S>
2796 template <
typename S>
2802 template <
typename S>
2808 template <
typename S>
2817 template <
typename S>
2824 template <
typename S>
2830 template <
typename S>
2836 template <
typename S>
2845 template <
typename S>
2852 template <
typename S>
2858 template <
typename S>
2864 template <
typename S>
2873 template <
typename S>
2880 template <
typename S>
2883 return &supportConvex<S>;
2886 template <
typename S>
2889 return ¢erConvex<S>;
2892 template <
typename S>
2901 template <
typename S>
2918 template <
typename S>
2923 Vector3<S> center((P1[0] + P2[0] + P3[0]) / 3, (P1[1] + P2[1] + P3[1]) / 3,
2924 (P1[2] + P2[2] + P3[2]) / 3);
2926 ccdVec3Set(&o->
p[0], P1[0], P1[1], P1[2]);
2927 ccdVec3Set(&o->
p[1], P2[0], P2[1], P2[2]);
2928 ccdVec3Set(&o->
p[2], P3[0], P3[1], P3[2]);
2929 ccdVec3Set(&o->
c, center[0], center[1], center[2]);
2930 ccdVec3Set(&o->
pos, 0., 0., 0.);
2931 ccdQuatSet(&o->
rot, 0., 0., 0., 1.);
2937 template <
typename S>
2942 Vector3<S> center((P1[0] + P2[0] + P3[0]) / 3, (P1[1] + P2[1] + P3[1]) / 3,
2943 (P1[2] + P2[2] + P3[2]) / 3);
2945 ccdVec3Set(&o->
p[0], P1[0], P1[1], P1[2]);
2946 ccdVec3Set(&o->
p[1], P2[0], P2[1], P2[2]);
2947 ccdVec3Set(&o->
p[2], P3[0], P3[1], P3[2]);
2948 ccdVec3Set(&o->
c, center[0], center[1], center[2]);
2951 ccdVec3Set(&o->
pos, T[0], T[1], T[2]);
2952 ccdQuatSet(&o->
rot, q.x(), q.y(), q.z(), q.w());