diff --git a/include/hpp/fcl/narrowphase/gjk.h b/include/hpp/fcl/narrowphase/gjk.h index b0d00aeb6cced477990a7964ccbd60e363c32683..416d56f6c64facc29b60285d06b8a96e57acd1b5 100644 --- a/include/hpp/fcl/narrowphase/gjk.h +++ b/include/hpp/fcl/narrowphase/gjk.h @@ -66,7 +66,11 @@ struct MinkowskiDiff /// @brief transform from shape1 to shape0 Transform3f toshape0; - MinkowskiDiff() { } + typedef void (*GetSupportFunction) (const MinkowskiDiff& minkowskiDiff, + const Vec3f& dir, bool dirIsNormalized, Vec3f& support); + GetSupportFunction getSupportFunc; + + MinkowskiDiff() : getSupportFunc (NULL) {} void set (const ShapeBase* shape0, const ShapeBase* shape1); @@ -88,6 +92,13 @@ struct MinkowskiDiff return support0(d) - support1(-d); } + /// @brief support function for the pair of shapes + inline void support(const Vec3f& d, bool dIsNormalized, Vec3f& supp) const + { + assert(getSupportFunc != NULL); + getSupportFunc(*this, d, dIsNormalized, supp); + } + /// @brief support function for the d-th shape (d = 0 or 1) inline Vec3f support(const Vec3f& d, size_t index) const { diff --git a/src/narrowphase/gjk.cpp b/src/narrowphase/gjk.cpp index 2e369554104fc1da68847f69aa55f89d40a4c62e..f390e2674cd5743990d092fff354fc59f5edd73a 100644 --- a/src/narrowphase/gjk.cpp +++ b/src/narrowphase/gjk.cpp @@ -46,6 +46,26 @@ namespace fcl namespace details { +struct shape_traits_base +{ + enum { NeedNormalizedDir = true + }; +}; + +template <typename Shape> struct shape_traits : shape_traits_base {}; + +template <> struct shape_traits<TriangleP> : shape_traits_base +{ + enum { NeedNormalizedDir = false + }; +}; + +template <> struct shape_traits<Box> : shape_traits_base +{ + enum { NeedNormalizedDir = false + }; +}; + void getShapeSupport(const TriangleP* triangle, const Vec3f& dir, Vec3f& support) { FCL_REAL dota = dir.dot(triangle->a); @@ -192,10 +212,78 @@ void getSupportTpl (const Shape0* s0, const Shape1* s1, support.noalias() -= oM1 * support1 + ot1; } +template <typename Shape0, typename Shape1> +void getSupportFuncTpl (const MinkowskiDiff& md, + const Vec3f& dir, bool dirIsNormalized, Vec3f& support) +{ + enum { NeedNormalizedDir = + bool ( (bool)shape_traits<Shape0>::NeedNormalizedDir + || (bool)shape_traits<Shape1>::NeedNormalizedDir) + }; + getSupportTpl<Shape0, Shape1> ( + static_cast <const Shape0*>(md.shapes[0]), + static_cast <const Shape1*>(md.shapes[1]), + md.toshape0.getRotation(), + md.toshape0.getTranslation(), + (NeedNormalizedDir && !dirIsNormalized) ? dir.normalized() : dir, + support); +} + +template <typename Shape0> +MinkowskiDiff::GetSupportFunction makeGetSupportFunction1 (const ShapeBase* s1) +{ + switch(s1->getNodeType()) + { + case GEOM_TRIANGLE: + return getSupportFuncTpl<Shape0, TriangleP>; + case GEOM_BOX: + return getSupportFuncTpl<Shape0, Box>; + case GEOM_SPHERE: + return getSupportFuncTpl<Shape0, Sphere>; + case GEOM_CAPSULE: + return getSupportFuncTpl<Shape0, Capsule>; + case GEOM_CONE: + return getSupportFuncTpl<Shape0, Cone>; + case GEOM_CYLINDER: + return getSupportFuncTpl<Shape0, Cylinder>; + case GEOM_CONVEX: + return getSupportFuncTpl<Shape0, Convex>; + default: + throw std::logic_error ("Unsupported geometric shape"); + } +} + void MinkowskiDiff::set (const ShapeBase* shape0, const ShapeBase* shape1) { shapes[0] = shape0; shapes[1] = shape1; + + switch(shape0->getNodeType()) + { + case GEOM_TRIANGLE: + getSupportFunc = makeGetSupportFunction1<TriangleP> (shape1); + break; + case GEOM_BOX: + getSupportFunc = makeGetSupportFunction1<Box> (shape1); + break; + case GEOM_SPHERE: + getSupportFunc = makeGetSupportFunction1<Sphere> (shape1); + break; + case GEOM_CAPSULE: + getSupportFunc = makeGetSupportFunction1<Capsule> (shape1); + break; + case GEOM_CONE: + getSupportFunc = makeGetSupportFunction1<Cone> (shape1); + break; + case GEOM_CYLINDER: + getSupportFunc = makeGetSupportFunction1<Cylinder> (shape1); + break; + case GEOM_CONVEX: + getSupportFunc = makeGetSupportFunction1<Convex> (shape1); + break; + default: + throw std::logic_error ("Unsupported geometric shape"); + } } void GJK::initialize()