diff --git a/include/hpp/fcl/narrowphase/gjk.h b/include/hpp/fcl/narrowphase/gjk.h
index 4748e3e087efa12a8238d0df311eec54ec7b544c..b0d00aeb6cced477990a7964ccbd60e363c32683 100644
--- a/include/hpp/fcl/narrowphase/gjk.h
+++ b/include/hpp/fcl/narrowphase/gjk.h
@@ -68,6 +68,8 @@ struct MinkowskiDiff
 
   MinkowskiDiff() { }
 
+  void set (const ShapeBase* shape0, const ShapeBase* shape1);
+
   /// @brief support function for shape0
   inline Vec3f support0(const Vec3f& d) const
   {
@@ -96,7 +98,6 @@ struct MinkowskiDiff
   }
 };
 
-
 /// @brief class for GJK algorithm
 ///
 /// \note The computations are performed in the frame of the first shape.
diff --git a/include/hpp/fcl/narrowphase/narrowphase.h b/include/hpp/fcl/narrowphase/narrowphase.h
index a85f7fae3131b7333d88401a4168af161bdaf42d..dc0720c992c61f3d40dd9820ed05cf7c882544b7 100644
--- a/include/hpp/fcl/narrowphase/narrowphase.h
+++ b/include/hpp/fcl/narrowphase/narrowphase.h
@@ -62,8 +62,7 @@ namespace fcl
       if(enable_cached_guess) guess = cached_guess;
     
       details::MinkowskiDiff shape;
-      shape.shapes[0] = &s1;
-      shape.shapes[1] = &s2;
+      shape.set (&s1, &s2);
       shape.toshape1 = tf2.getRotation().transpose() * tf1.getRotation();
       shape.toshape0 = tf1.inverseTimes(tf2);
   
@@ -115,8 +114,7 @@ namespace fcl
       if(enable_cached_guess) guess = cached_guess;
 
       details::MinkowskiDiff shape;
-      shape.shapes[0] = &s;
-      shape.shapes[1] = &tri;
+      shape.set (&s, &tri);
       shape.toshape1 = tf2.getRotation().transpose() * tf1.getRotation();
       shape.toshape0 = tf1.inverseTimes(tf2);
   
@@ -183,8 +181,7 @@ namespace fcl
       if(enable_cached_guess) guess = cached_guess;
 
       details::MinkowskiDiff shape;
-      shape.shapes[0] = &s1;
-      shape.shapes[1] = &s2;
+      shape.set (&s1, &s2);
       shape.toshape1 = tf2.getRotation().transpose() * tf1.getRotation();
       shape.toshape0 = tf1.inverseTimes(tf2);
 
diff --git a/src/narrowphase/gjk.cpp b/src/narrowphase/gjk.cpp
index 9d18ac52965ab48934da561ab811d3c0a74aa45d..2e369554104fc1da68847f69aa55f89d40a4c62e 100644
--- a/src/narrowphase/gjk.cpp
+++ b/src/narrowphase/gjk.cpp
@@ -46,129 +46,156 @@ namespace fcl
 namespace details
 {
 
+void getShapeSupport(const TriangleP* triangle, const Vec3f& dir, Vec3f& support)
+{
+  FCL_REAL dota = dir.dot(triangle->a);
+  FCL_REAL dotb = dir.dot(triangle->b);
+  FCL_REAL dotc = dir.dot(triangle->c);
+  if(dota > dotb)
+  {
+    if(dotc > dota)
+      support = triangle->c;
+    else
+      support = triangle->a;
+  }
+  else
+  {
+    if(dotc > dotb)
+      support = triangle->c;
+    else
+      support = triangle->b;
+  }
+}
+
+inline void getShapeSupport(const Box* box, const Vec3f& dir, Vec3f& support)
+{
+  support.noalias() = (dir.array() > 0).select(box->halfSide, -box->halfSide);
+}
+
+inline void getShapeSupport(const Sphere* sphere, const Vec3f& dir, Vec3f& support)
+{
+  support = dir * sphere->radius;
+}
+
+inline void getShapeSupport(const Capsule* capsule, const Vec3f& dir, Vec3f& support)
+{
+  support = capsule->radius * dir;
+  if (dir[2] > 0) support[2] += capsule->lz / 2;
+  else            support[2] -= capsule->lz / 2;
+}
+
+void getShapeSupport(const Cone* cone, const Vec3f& dir, Vec3f& support)
+{
+  // TODO (Joseph Mirabel)
+  // this assumes that the cone radius is, for -0.5 < z < 0.5:
+  // (lz/2 - z) * radius / lz
+  //
+  // I did not change the code myself. However, I think it should be revised.
+  // 1. It can be optimized.
+  // 2. I am not sure this is what conePlaneIntersect and coneHalfspaceIntersect
+  //    assumes...
+  FCL_REAL zdist = dir[0] * dir[0] + dir[1] * dir[1];
+  FCL_REAL len = zdist + dir[2] * dir[2];
+  zdist = std::sqrt(zdist);
+  len = std::sqrt(len);
+  FCL_REAL half_h = cone->lz * 0.5;
+  FCL_REAL radius = cone->radius;
+
+  FCL_REAL sin_a = radius / std::sqrt(radius * radius + 4 * half_h * half_h);
+
+  if(dir[2] > len * sin_a)
+    support = Vec3f(0, 0, half_h);
+  else if(zdist > 0)
+  {
+    FCL_REAL rad = radius / zdist;
+    support = Vec3f(rad * dir[0], rad * dir[1], -half_h);
+  }
+  else
+    support = Vec3f(0, 0, -half_h);
+}
+
+void getShapeSupport(const Cylinder* cylinder, const Vec3f& dir, Vec3f& support)
+{
+  static const FCL_REAL eps (sqrt(std::numeric_limits<FCL_REAL>::epsilon()));
+  FCL_REAL zdist = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
+  FCL_REAL half_h = cylinder->lz * 0.5;
+  if(zdist == 0.0)
+    support = Vec3f(0, 0, (dir[2]>0)? half_h:-half_h);
+  else {
+    FCL_REAL d = cylinder->radius / zdist;
+    FCL_REAL z (0.);
+    if (dir [2] > eps) z = half_h;
+    else if (dir [2] < -eps) z = -half_h;
+    support << d * dir.head<2>(), z;
+  }
+  assert (fabs (support [0] * dir [1] - support [1] * dir [0]) < eps);
+}
+
+void getShapeSupport(const Convex* convex, const Vec3f& dir, Vec3f& support)
+{
+  FCL_REAL maxdot = - std::numeric_limits<FCL_REAL>::max();
+  Vec3f* curp = convex->points;
+  for(int i = 0; i < convex->num_points; ++i, curp+=1)
+  {
+    FCL_REAL dot = dir.dot(*curp);
+    if(dot > maxdot)
+    {
+      support = *curp;
+      maxdot = dot;
+    }
+  }
+}
+
 Vec3f getSupport(const ShapeBase* shape, const Vec3f& dir)
 {
-  FCL_REAL eps (sqrt(std::numeric_limits<FCL_REAL>::epsilon()));
+  Vec3f support;
   switch(shape->getNodeType())
   {
   case GEOM_TRIANGLE:
-    {
-      const TriangleP* triangle = static_cast<const TriangleP*>(shape);
-      FCL_REAL dota = dir.dot(triangle->a);
-      FCL_REAL dotb = dir.dot(triangle->b);
-      FCL_REAL dotc = dir.dot(triangle->c);
-      if(dota > dotb)
-      {
-        if(dotc > dota)
-          return triangle->c;
-        else
-          return triangle->a;
-      }
-      else
-      {
-        if(dotc > dotb)
-          return triangle->c;
-        else
-          return triangle->b;
-      }
-    }
+    getShapeSupport (static_cast<const TriangleP*>(shape), dir, support);
     break;
   case GEOM_BOX:
-    {
-      const Box* box = static_cast<const Box*>(shape);
-      return (dir.array() > 0).select(box->halfSide, -box->halfSide);
-    }
+    getShapeSupport (static_cast<const Box*>(shape), dir, support);
     break;
   case GEOM_SPHERE:
-    {
-      const Sphere* sphere = static_cast<const Sphere*>(shape);
-      return dir * sphere->radius;
-    }
+    getShapeSupport (static_cast<const Sphere*>(shape), dir, support);
     break;
   case GEOM_CAPSULE:
-    {
-      const Capsule* capsule = static_cast<const Capsule*>(shape);
-      FCL_REAL half_h = capsule->lz * 0.5;
-      Vec3f pos1(0, 0, half_h);
-      Vec3f pos2(0, 0, -half_h);
-      Vec3f v = dir * capsule->radius;
-      pos1 += v;
-      pos2 += v;
-      if(dir.dot(pos1) > dir.dot(pos2))
-        return pos1;
-      else return pos2;
-    }
+    getShapeSupport (static_cast<const Capsule*>(shape), dir, support);
     break;
   case GEOM_CONE:
-    {
-      const Cone* cone = static_cast<const Cone*>(shape);
-      FCL_REAL zdist = dir[0] * dir[0] + dir[1] * dir[1];
-      FCL_REAL len = zdist + dir[2] * dir[2];
-      zdist = std::sqrt(zdist);
-      len = std::sqrt(len);
-      FCL_REAL half_h = cone->lz * 0.5;
-      FCL_REAL radius = cone->radius;
-
-      FCL_REAL sin_a = radius / std::sqrt(radius * radius + 4 * half_h * half_h);
-
-      if(dir[2] > len * sin_a)
-        return Vec3f(0, 0, half_h);
-      else if(zdist > 0)
-      {
-        FCL_REAL rad = radius / zdist;
-        return Vec3f(rad * dir[0], rad * dir[1], -half_h);
-      }
-      else
-        return Vec3f(0, 0, -half_h);
-    }
+    getShapeSupport (static_cast<const Cone*>(shape), dir, support);
     break;
   case GEOM_CYLINDER:
-    {
-      const Cylinder* cylinder = static_cast<const Cylinder*>(shape);
-      FCL_REAL zdist = std::sqrt(dir[0] * dir[0] + dir[1] * dir[1]);
-      FCL_REAL half_h = cylinder->lz * 0.5;
-      Vec3f res;
-      if(zdist == 0.0)
-      {
-        res =  Vec3f(0, 0, (dir[2]>0)? half_h:-half_h);
-      }
-      else
-      {
-        FCL_REAL d = cylinder->radius / zdist;
-        FCL_REAL z (0.);
-        if (dir [2] > eps) z = half_h;
-        else if (dir [2] < -eps) z = -half_h;
-        res =  Vec3f(d * dir[0], d * dir[1], z);
-      }
-      assert (fabs (res [0] * dir [1] - res [1] * dir [0]) < eps);
-      return res;
-    }
+    getShapeSupport (static_cast<const Cylinder*>(shape), dir, support);
     break;
   case GEOM_CONVEX:
-    {
-      const Convex* convex = static_cast<const Convex*>(shape);
-      FCL_REAL maxdot = - std::numeric_limits<FCL_REAL>::max();
-      Vec3f* curp = convex->points;
-      Vec3f bestv(0,0,0);
-      for(int i = 0; i < convex->num_points; ++i, curp+=1)
-      {
-        FCL_REAL dot = dir.dot(*curp);
-        if(dot > maxdot)
-        {
-          bestv = *curp;
-          maxdot = dot;
-        }
-      }
-      return bestv;
-    }
+    getShapeSupport (static_cast<const Convex*>(shape), dir, support);
     break;
   case GEOM_PLANE:
-	break;
+  case GEOM_HALFSPACE:
   default:
     ; // nothing
   }
 
-  return Vec3f(0, 0, 0);
+  return support;
+}
+
+template <typename Shape0, typename Shape1>
+void getSupportTpl (const Shape0* s0, const Shape1* s1,
+    const Matrix3f& oM1, const Vec3f& ot1,
+    const Vec3f& dir, Vec3f& support)
+{
+  getShapeSupport (s0, dir, support);
+  Vec3f support1;
+  getShapeSupport (s1, - oM1.transpose() * dir, support1);
+  support.noalias() -= oM1 * support1 + ot1;
+}
+
+void MinkowskiDiff::set (const ShapeBase* shape0, const ShapeBase* shape1)
+{
+  shapes[0] = shape0;
+  shapes[1] = shape1;
 }
 
 void GJK::initialize()
@@ -181,13 +208,11 @@ void GJK::initialize()
   simplex = NULL;
 }
 
-
 Vec3f GJK::getGuessFromSimplex() const
 {
   return ray;
 }
 
-
 GJK::Status GJK::evaluate(const MinkowskiDiff& shape_, const Vec3f& guess)
 {
   size_t iterations = 0;
@@ -209,7 +234,6 @@ GJK::Status GJK::evaluate(const MinkowskiDiff& shape_, const Vec3f& guess)
   simplices[0].rank = 0;
   ray = guess;
 
-  // appendVertex(simplices[0], (ray.squaredNorm() > 0) ? -ray : Vec3f(1, 0, 0));
   if (ray.squaredNorm() > 0) appendVertex(simplices[0], -ray);
   else                       appendVertex(simplices[0], Vec3f(1, 0, 0));
   simplices[0].coefficient[0] = 1;
@@ -390,7 +414,6 @@ bool GJK::encloseOrigin()
   return false;
 }
 
-
 void EPA::initialize()
 {
   sv_store = new SimplexV[max_vertex_num];
diff --git a/src/narrowphase/narrowphase.cpp b/src/narrowphase/narrowphase.cpp
index a54333ef23d3675cae4f4a57857d16bae4cb5d46..32de8492b96c31b6bd365ecaa50039c83e7b418c 100644
--- a/src/narrowphase/narrowphase.cpp
+++ b/src/narrowphase/narrowphase.cpp
@@ -630,8 +630,7 @@ bool GJKSolver_indep::shapeDistance<Capsule, Capsule>
     bool enable_penetration (true);
 
     details::MinkowskiDiff shape;
-    shape.shapes[0] = &s1;
-    shape.shapes[1] = &s2;
+    shape.set (&s1, &s2);
     shape.toshape1 = tf2.getRotation().transpose() * tf1.getRotation();
     shape.toshape0 = tf1.inverseTimes(tf2);