danfis / libccd

Library for collision detection between two convex shapes
Other
478 stars 108 forks source link

ccdGJKPenetration: Segmentation fault #22

Open ngupta1024 opened 7 years ago

ngupta1024 commented 7 years ago

I am getting a segmentation fault when trying to implement ccdGJKPenetration. I think it is most probably because of the variable (nearest) that has been defined as a pointer but not allocated any memory. I am a beginner, so I would like you to provide your opinion on the same.

danfis commented 7 years ago

If you want to solve this problem, you have to provide more detailed information. Preferably post a complete code and point out where is the problem.

infdivzero commented 1 year ago

If this is the same segmentation fault I'm running into with my program, it's an address boundary error caused by nextSupport() in ccd.c at line 961. Further up this trace from valgrind we find __ccdGJKEPA() calls nextSupport():

    while (1){
        // get triangle nearest to origin
        *nearest = ccdPtNearest(polytope);

        // get next support point
        if (nextSupport(obj1, obj2, ccd, *nearest, &supp) != 0)
            break;

        // expand nearest triangle using new point - supp
        if (expandPolytope(polytope, *nearest, &supp) != 0)
            return -2;
    }

After tossing a printf into _ccdPtNearestRenew() I found nearest doesn't get set and it's left null after the 3 _ccdPtNearestUpdate() calls in _ccdPtNearestRenew(), which ccdPtNearest() calls if nearest is null.

I think it could be a mathematical robustness issue. Tossing a printf into _ccdPtNearestUpdate() shows el->dist == -nan and pt->nearest_dist == some very big number.

_ccd_inline void _ccdPtNearestUpdate(ccd_pt_t *pt, ccd_pt_el_t *el)
{
    if (ccdEq(pt->nearest_dist, el->dist)){
        if (el->type < pt->nearest_type){
            pt->nearest = el;
            pt->nearest_dist = el->dist;
            pt->nearest_type = el->type;
        }
    }else if (el->dist < pt->nearest_dist){
        pt->nearest = el;
        pt->nearest_dist = el->dist;
        pt->nearest_type = el->type;
    }

    // pt->nearest remains null
    printf("dists: %f %f\n", pt->nearest_dist, el->dist);
}
static void _ccdPtNearestRenew(ccd_pt_t *pt)
{
    ccd_pt_vertex_t *v;
    ccd_pt_edge_t *e;
    ccd_pt_face_t *f;

    pt->nearest_dist = CCD_REAL_MAX;
    pt->nearest_type = 3;
    pt->nearest = NULL;

    ccdListForEachEntry(&pt->vertices, v, ccd_pt_vertex_t, list){
        _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)v);
    }

    ccdListForEachEntry(&pt->edges, e, ccd_pt_edge_t, list){
        _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)e);
    }

    ccdListForEachEntry(&pt->faces, f, ccd_pt_face_t, list){
        _ccdPtNearestUpdate(pt, (ccd_pt_el_t *)f);
    }
}
ccd_pt_el_t *ccdPtNearest(ccd_pt_t *pt)
{
    if (!pt->nearest){
        _ccdPtNearestRenew(pt);
    }
    return pt->nearest;
}