def METHOD_NAME(obj, qhull_options='QbB Pp Qt', repair=True):
    """
    Get a new Trimesh object representing the convex hull of the
    current mesh attempting to return a watertight mesh with correct
    normals.
    Details on qhull options:
      http://www.qhull.org/html/qh-quick.htm#options
    Arguments
    --------
    obj : Trimesh, or (n,3) float
      Mesh or cartesian points
    qhull_options : str
      Options to pass to qhull.
    Returns
    --------
    convex : Trimesh
      Mesh of convex hull
    """
    from .base import Trimesh
    if isinstance(obj, Trimesh):
        points = obj.vertices.view(np.ndarray)
    else:
        # will remove subclassing
        points = np.asarray(obj, dtype=np.float64)
        if not util.is_shape(points, (-1, 3)):
            raise ValueError('Object must be Trimesh or (n,3) points!')
    try:
        hull = ConvexHull(points, qhull_options=qhull_options)
    except QhullError:
        util.log.debug(
            'Failed to compute convex hull: retrying with `QJ`',
            exc_info=True)
        # try with "joggle" enabled
        hull = ConvexHull(points, qhull_options='QJ')
    # hull object doesn't remove unreferenced vertices
    # create a mask to re- index faces for only referenced vertices
    vid = np.sort(hull.vertices)
    mask = np.zeros(len(hull.points), dtype=np.int64)
    mask[vid] = np.arange(len(vid))
    # remove unreferenced vertices here
    faces = mask[hull.simplices].copy()
    # rescale vertices back to original size
    vertices = hull.points[vid].copy()
    if not repair:
        # create the Trimesh object for the convex hull
        return Trimesh(vertices=vertices,
                       faces=faces,
                       process=True,
                       validate=False)
    # qhull returns faces with random winding
    # calculate the returned normal of each face
    crosses = triangles.cross(vertices[faces])
    # qhull returns zero magnitude faces like an asshole
    normals, valid = util.unitize(crosses, check_valid=True)
    # remove zero magnitude faces
    faces = faces[valid]
    crosses = crosses[valid]
    # each triangle area and mean center
    triangles_area = triangles.area(crosses=crosses, sum=False)
    triangles_center = vertices[faces].mean(axis=1)
    # since the convex hull is (hopefully) convex, the vector from
    # the centroid to the center of each face
    # should have a positive dot product with the normal of that face
    # if it doesn't it is probably backwards
    # note that this sometimes gets screwed up by precision issues
    centroid = np.average(triangles_center,
                          weights=triangles_area,
                          axis=0)
    # a vector from the centroid to a point on each face
    test_vector = triangles_center - centroid
    # check the projection against face normals
    backwards = util.diagonal_dot(normals, test_vector) < 0.0
    # flip the winding outward facing
    faces[backwards] = np.fliplr(faces[backwards])
    # flip the normal
    normals[backwards] *= -1.0
    # save the work we did to the cache so it doesn't have to be recomputed
    initial_cache = {'triangles_cross': crosses,
                     'triangles_center': triangles_center,
                     'area_faces': triangles_area,
                     'centroid': centroid}
    # create the Trimesh object for the convex hull
    convex = Trimesh(vertices=vertices,
                     faces=faces,
                     face_normals=normals,
                     initial_cache=initial_cache,
                     process=True,
                     validate=False)
    # we did the gross case above, but sometimes precision issues
    # leave some faces backwards anyway
    # this call will exit early if the winding is consistent
    # and if not will fix it by traversing the adjacency graph
    convex.fix_normals(multibody=False)
    # sometimes the QbB option will cause precision issues
    # so try the hull again without it and
    # check for qhull_options is None to avoid infinite recursion
    if (qhull_options is not None and
            not convex.is_winding_consistent):
        return METHOD_NAME(convex, qhull_options=None)
    return convex