Simple ray casting query: Difference between revisions

From ODE
Jump to navigationJump to search
imported>Jazztickets
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..."
 
imported>Jazztickets
more clean up
 
(One intermediate revision by the same user not shown)
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
     dGeomID Ray = dCreateRay(0, Length);
     dGeomID Ray = dCreateRay(0, Length);
     dGeomRaySet(Ray, Start[0], Start[1], Start[2], Direction[0], Direction[1], Direction[2]);
     dGeomRaySet(Ray, Start[0], Start[1], Start[2], Direction[0], Direction[1], Direction[2]);
    dGeomSetCategoryBits(Ray, 0);
    dGeomSetCollideBits(Ray, _Physics::FILTER_CAMERA);
   
   
     // Check collisions
     // Check collisions
Line 56: Line 51:
     // 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;

Latest revision as of 13:28, 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]);

    // 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;
}