Difference between revisions of "Simple ray casting query"

From ODE
Jump to: navigation, search
(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...")
 
(cleaned up code)
Line 1: Line 1:
 
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.
 
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.
 
+
#include <ode/odemath.h>
 +
#include <ode/collision.h>
 +
#include <ode/objects.h>
 +
 
  const int MAX_CONTACTS = 32;
 
  const int MAX_CONTACTS = 32;
 
   
 
   
Line 14: Line 17:
 
         // Check depth against current closest hit
 
         // Check depth against current closest hit
 
         if(Contacts[i].geom.depth < HitPosition[3]) {
 
         if(Contacts[i].geom.depth < HitPosition[3]) {
             HitPosition[0] = Contacts[i].geom.pos[0];
+
             dCopyVector3(HitPosition, Contacts[i].geom.pos);
            HitPosition[1] = Contacts[i].geom.pos[1];
 
            HitPosition[2] = Contacts[i].geom.pos[2];
 
 
             HitPosition[3] = Contacts[i].geom.depth;
 
             HitPosition[3] = Contacts[i].geom.depth;
 
         }
 
         }
 
     }
 
     }
 
  }
 
  }
 
+
 
  // Performs raycasting on a space and returns the point of collision. Return false for no hit.
 
  // 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) {
 
  bool RaycastQuery(dSpaceID Space, const dVector3 Start, dVector3 End) {
Line 27: Line 28:
 
     // Calculate direction
 
     // Calculate direction
 
     dVector3 Direction;
 
     dVector3 Direction;
     Direction[0] = End[0] - Start[0];
+
     dSubtractVectors3(Direction, End, Start);
    Direction[1] = End[1] - Start[1];
 
    Direction[2] = End[2] - Start[2];
 
 
   
 
   
 
     // Get length
 
     // Get length
     dReal Length = dSqrt(Direction[0] * Direction[0] + Direction[1] * Direction[1] + Direction[2] * Direction[2]);
+
     dReal Length = dCalcVectorLength3(Direction);
 
     dReal InverseLength = dRecip(Length);
 
     dReal InverseLength = dRecip(Length);
 
   
 
   
 
     // Normalize
 
     // Normalize
     Direction[0] *= InverseLength;
+
     dScaleVector3(Direction, InverseLength);
    Direction[1] *= InverseLength;
 
    Direction[2] *= InverseLength;
 
 
   
 
   
 
     // Create ray
 
     // Create ray
Line 56: Line 53:
 
     // Check for hit
 
     // Check for hit
 
     if(HitPosition[3] != dInfinity) {
 
     if(HitPosition[3] != dInfinity) {
         End[0] = HitPosition[0];
+
         dCopyVector3(End, HitPosition);
        End[1] = HitPosition[1];
 
        End[2] = HitPosition[2];
 
 
   
 
   
 
         return true;
 
         return true;

Revision as of 12:27, 24 March 2019

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.

#include <ode/odemath.h>
#include <ode/collision.h>
#include <ode/objects.h>

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]) {
            dCopyVector3(HitPosition, Contacts[i].geom.pos);
            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;
    dSubtractVectors3(Direction, End, Start);

    // Get length
    dReal Length = dCalcVectorLength3(Direction);
    dReal InverseLength = dRecip(Length);

    // Normalize
    dScaleVector3(Direction, 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) {
        dCopyVector3(End, HitPosition);

        return true;
    }

    return false;
}