From d42d61d5eee82fa8fb85b93f6cbb70b46eddefda Mon Sep 17 00:00:00 2001
From: Joseph Mirabel <jmirabel@laas.fr>
Date: Thu, 22 Aug 2019 18:54:57 +0200
Subject: [PATCH] [OBB] Reimplement obbDisjointAndLowerBoundDistance according
 to bench

test_fcl_obb.
---
 src/BV/OBB.cpp | 108 +++++++++++++++++++++++++++++++++++--------------
 1 file changed, 77 insertions(+), 31 deletions(-)

diff --git a/src/BV/OBB.cpp b/src/BV/OBB.cpp
index aed6c595..1f13f021 100644
--- a/src/BV/OBB.cpp
+++ b/src/BV/OBB.cpp
@@ -294,6 +294,71 @@ bool obbDisjoint(const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f&
 
 }
 
+namespace internal
+{
+  inline FCL_REAL obbDisjoint_check_A_axis (
+      const Vec3f& T, const Vec3f& a, const Vec3f& b, const Matrix3f& Bf)
+  {
+    // |T| - |B| * b - a
+    Vec3f AABB_corner (T.cwiseAbs () - a);
+    AABB_corner.noalias() -= Bf.col(0) * b[0];
+    AABB_corner.noalias() -= Bf.col(1) * b[1];
+    AABB_corner.noalias() -= Bf.col(2) * b[2];
+    return AABB_corner.array().max(0).matrix().squaredNorm ();
+  }
+
+  inline FCL_REAL obbDisjoint_check_B_axis (
+      const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f& b, const Matrix3f& Bf)
+  {
+    // Bf = |B|
+    // | B^T T| - Bf^T * a - b
+    register FCL_REAL s, t = 0;
+    s = std::abs(B.col(0).dot(T)) - Bf.col(0).dot(a) - b[0];
+    if (s > 0) t += s*s;
+    s = std::abs(B.col(1).dot(T)) - Bf.col(1).dot(a) - b[1];
+    if (s > 0) t += s*s;
+    s = std::abs(B.col(2).dot(T)) - Bf.col(2).dot(a) - b[2];
+    if (s > 0) t += s*s;
+    return t;
+  }
+
+  template <int ib, int jb = (ib+1)%3, int kb = (ib+2)%3 >
+  struct obbDisjoint_check_Ai_cross_Bi
+  {
+    static inline bool run (int ia, int ja, int ka,
+        const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f& b,
+        const Matrix3f& Bf,
+        const FCL_REAL& breakDistance2, FCL_REAL& squaredLowerBoundDistance)
+    {
+      const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib);
+
+      const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) +
+                                       b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb));
+      // We need to divide by the norm || Aia x Bib ||
+      // As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2  = cosine^2
+      if (diff > 0) {
+        FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib);
+        if (sinus2 > 1e-6) {
+          squaredLowerBoundDistance = diff * diff / sinus2;
+          if (squaredLowerBoundDistance > breakDistance2) {
+            return true;
+          }
+        }
+        /* // or
+           FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib);
+           squaredLowerBoundDistance = diff * diff;
+           if (squaredLowerBoundDistance > breakDistance2 * sinus2) {
+           squaredLowerBoundDistance /= sinus2;
+           return true;
+           }
+        // */
+      }
+      return false;
+    }
+  };
+}
+
+
 // B, T orientation and position of 2nd OBB in frame of 1st OBB,
 // a extent of 1st OBB,
 // b extent of 2nd OBB.
@@ -301,58 +366,39 @@ bool obbDisjoint(const Matrix3f& B, const Vec3f& T, const Vec3f& a, const Vec3f&
 // This function tests whether bounding boxes should be broken down.
 //
 bool obbDisjointAndLowerBoundDistance (const Matrix3f& B, const Vec3f& T,
-				       const Vec3f& a, const Vec3f& b,
+                                       const Vec3f& a, const Vec3f& b,
                                        const CollisionRequest& request,
-				       FCL_REAL& squaredLowerBoundDistance)
+                                       FCL_REAL& squaredLowerBoundDistance)
 {
   const FCL_REAL breakDistance (request.break_distance + request.security_margin);
   const FCL_REAL breakDistance2 = breakDistance * breakDistance;
-  Vec3f AABB_corner;
 
   Matrix3f Bf (B.cwiseAbs());
 
   // Corner of b axis aligned bounding box the closest to the origin
-  AABB_corner.noalias() = T.cwiseAbs () - Bf * b - a;
-  squaredLowerBoundDistance = AABB_corner.array().max(0).matrix().squaredNorm ();
+  squaredLowerBoundDistance = internal::obbDisjoint_check_A_axis (T, a, b, Bf);
   if (squaredLowerBoundDistance > breakDistance2)
     return true;
 
-  // | B^T T| - b - Bf^T a
-  AABB_corner.noalias() = (B.transpose () * T).cwiseAbs ()  - Bf.transpose () * a - b;
-  squaredLowerBoundDistance = AABB_corner.array().max(0).matrix().squaredNorm();
+  squaredLowerBoundDistance = internal::obbDisjoint_check_B_axis (B, T, a, b, Bf);
   if (squaredLowerBoundDistance > breakDistance2)
     return true;
 
-  int ja = 1, ka = 2, jb = 1, kb = 2;
+  // Ai x Bj
+  int ja = 1, ka = 2;
   for (int ia = 0; ia < 3; ++ia) {
-    for (int ib = 0; ib < 3; ++ib) {
-      const FCL_REAL s = T[ka] * B(ja, ib) - T[ja] * B(ka, ib);
-
-      const FCL_REAL diff = fabs(s) - (a[ja] * Bf(ka, ib) + a[ka] * Bf(ja, ib) +
-                                       b[jb] * Bf(ia, kb) + b[kb] * Bf(ia, jb));
-      // We need to divide by the norm || Aia x Bib ||
-      // As ||Aia|| = ||Bib|| = 1, (Aia | Bib)^2  = cosine^2
-      if (diff > 0) {
-        FCL_REAL sinus2 = 1 - Bf (ia,ib) * Bf (ia,ib);
-        if (sinus2 > 1e-6) {
-          squaredLowerBoundDistance = diff * diff / sinus2;
-          if (squaredLowerBoundDistance > breakDistance2) {
-            return true;
-          }
-        }
-      }
-
-      jb = kb; kb = ib;
-    }
+    if (internal::obbDisjoint_check_Ai_cross_Bi<0>::run (ia, ja, ka,
+          B, T, a, b, Bf, breakDistance2, squaredLowerBoundDistance)) return true;
+    if (internal::obbDisjoint_check_Ai_cross_Bi<1>::run (ia, ja, ka,
+          B, T, a, b, Bf, breakDistance2, squaredLowerBoundDistance)) return true;
+    if (internal::obbDisjoint_check_Ai_cross_Bi<2>::run (ia, ja, ka,
+          B, T, a, b, Bf, breakDistance2, squaredLowerBoundDistance)) return true;
     ja = ka; ka = ia;
   }
 
   return false;
-
 }
 
-
-
 bool OBB::overlap(const OBB& other) const
 {
   /// compute what transform [R,T] that takes us from cs1 to cs2.
-- 
GitLab