Simple ray casting query

From ODE
Revision as of 10:30, 24 March 2019 by Jazztickets (talk | contribs) (Created page with "Unlike most physics engines, ODE has no built-in ray casting query function. However, you can easily create one using dSpaceCollide2. Other modifications could be made to incl...")
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

Unlike most physics engines, ODE has no built-in ray casting query function. However, you can easily create one using dSpaceCollide2. Other modifications could be made to include the hit geometry, for example.

const int MAX_CONTACTS = 32;

// Check ray collision against a space
void RayCallback(void *Data, dGeomID Geometry1, dGeomID Geometry2) {
    dReal *HitPosition = (dReal *)Data;

    // Check collisions
    dContact Contacts[MAX_CONTACTS];
    int Count = dCollide(Geometry1, Geometry2, MAX_CONTACTS, &Contacts[0].geom, sizeof(dContact));
    for(int i = 0; i < Count; i++) {

        // Check depth against current closest hit
        if(Contacts[i].geom.depth < HitPosition[3]) {
            HitPosition[0] = Contacts[i].geom.pos[0];
            HitPosition[1] = Contacts[i].geom.pos[1];
            HitPosition[2] = Contacts[i].geom.pos[2];
            HitPosition[3] = Contacts[i].geom.depth;
        }
    }
}
// Performs raycasting on a space and returns the point of collision. Return false for no hit.
bool RaycastQuery(dSpaceID Space, const dVector3 Start, dVector3 End) {
     
    // Calculate direction
    dVector3 Direction;
    Direction[0] = End[0] - Start[0];
    Direction[1] = End[1] - Start[1];
    Direction[2] = End[2] - Start[2];

    // Get length
    dReal Length = dSqrt(Direction[0] * Direction[0] + Direction[1] * Direction[1] + Direction[2] * Direction[2]);
    dReal InverseLength = dRecip(Length);

    // Normalize
    Direction[0] *= InverseLength;
    Direction[1] *= InverseLength;
    Direction[2] *= InverseLength;

    // Create ray
    dGeomID Ray = dCreateRay(0, Length);
    dGeomRaySet(Ray, Start[0], Start[1], Start[2], Direction[0], Direction[1], Direction[2]);
    dGeomSetCategoryBits(Ray, 0);
    dGeomSetCollideBits(Ray, _Physics::FILTER_CAMERA);

    // Check collisions
    dVector4 HitPosition;
    HitPosition[3] = dInfinity;
    dSpaceCollide2(Ray, (dGeomID)Space, HitPosition, &RayCallback);

    // Cleanup
    dGeomDestroy(Ray);

    // Check for hit
    if(HitPosition[3] != dInfinity) {
        End[0] = HitPosition[0];
        End[1] = HitPosition[1];
        End[2] = HitPosition[2];

        return true;
    }

    return false;
}