src/collision/shapes/TriangleShape.cpp
bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& /*allocator*/) const {

    RP3D_PROFILE("TriangleShape::raycast()", mProfiler);

    const Vector3 pq = ray.point2 - ray.point1;
    const Vector3 pa = mPoints[0] - ray.point1;
    const Vector3 pb = mPoints[1] - ray.point1;
    const Vector3 pc = mPoints[2] - ray.point1;

    // Test if the line PQ is inside the eges BC, CA and AB. We use the triple
    // product for this test.
    const Vector3 m = pq.cross(pc);
    decimal u = pb.dot(m);
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (u < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (u > decimal(0.0)) return false;
    }

    decimal v = -pa.dot(m);
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (v < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (v > decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::FRONT_AND_BACK) {
        if (!sameSign(u, v)) return false;
    }

    decimal w = pa.dot(pq.cross(pb));
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (w < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (w > decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::FRONT_AND_BACK) {
        if (!sameSign(u, w)) return false;
    }

    // If the line PQ is in the triangle plane (case where u=v=w=0)
    if (approxEqual(u, 0) && approxEqual(v, 0) && approxEqual(w, 0)) return false;

    // Compute the barycentric coordinates (u, v, w) to determine the
    // intersection point R, R = u * a + v * b + w * c
    decimal denom = decimal(1.0) / (u + v + w);
    u *= denom;
    v *= denom;
    w *= denom;

    // Compute the local hit point using the barycentric coordinates
    const Vector3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
    const decimal hitFraction = (localHitPoint - ray.point1).length() / pq.length();

    if (hitFraction < decimal(0.0) || hitFraction > ray.maxFraction) return false;

    // Compute the triangle face normal
    Vector3 normal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
    normal.normalize();
    normal = normal.dot(pq) > decimal(0.0) ? -normal : normal;

    raycastInfo.body = collider->getBody();
    raycastInfo.collider = collider;
    raycastInfo.worldPoint = localHitPoint;
    raycastInfo.hitFraction = hitFraction;
    raycastInfo.worldNormal = normal;

    return true;
}
// Raycast method with feedback information
/// This method use the line vs triangle raycasting technique described in
/// Real-time Collision Detection by Christer Ericson.
Raycast method with feedback information
This method use the line vs triangle raycasting technique described in
Real-time Collision Detection by Christer Ericson.
Raycast method with feedback information This method use the line vs triangle raycasting technique described in Real - time Collision Detection by Christer Ericson .
bool TriangleShape::raycast(const Ray& ray, RaycastInfo& raycastInfo, Collider* collider, MemoryAllocator& ) const {
    RP3D_PROFILE("TriangleShape::raycast()", mProfiler);
    const Vector3 pq = ray.point2 - ray.point1;
    const Vector3 pa = mPoints[0] - ray.point1;
    const Vector3 pb = mPoints[1] - ray.point1;
    const Vector3 pc = mPoints[2] - ray.point1;
    const Vector3 m = pq.cross(pc);
    decimal u = pb.dot(m);
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (u < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (u > decimal(0.0)) return false;
    }
    decimal v = -pa.dot(m);
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (v < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (v > decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::FRONT_AND_BACK) {
        if (!sameSign(u, v)) return false;
    }
    decimal w = pa.dot(pq.cross(pb));
    if (mRaycastTestType == TriangleRaycastSide::FRONT) {
        if (w < decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::BACK) {
        if (w > decimal(0.0)) return false;
    }
    else if (mRaycastTestType == TriangleRaycastSide::FRONT_AND_BACK) {
        if (!sameSign(u, w)) return false;
    }
    if (approxEqual(u, 0) && approxEqual(v, 0) && approxEqual(w, 0)) return false;
    decimal denom = decimal(1.0) / (u + v + w);
    u *= denom;
    v *= denom;
    w *= denom;
    const Vector3 localHitPoint = u * mPoints[0] + v * mPoints[1] + w * mPoints[2];
    const decimal hitFraction = (localHitPoint - ray.point1).length() / pq.length();
    if (hitFraction < decimal(0.0) || hitFraction > ray.maxFraction) return false;
    Vector3 normal = (mPoints[1] - mPoints[0]).cross(mPoints[2] - mPoints[0]);
    normal.normalize();
    normal = normal.dot(pq) > decimal(0.0) ? -normal : normal;
    raycastInfo.body = collider->getBody();
    raycastInfo.collider = collider;
    raycastInfo.worldPoint = localHitPoint;
    raycastInfo.hitFraction = hitFraction;
    raycastInfo.worldNormal = normal;
    return true;
}
bool TriangleShape :: raycast ( const Ray & ray , RaycastInfo & raycastInfo , Collider * collider , MemoryAllocator & ) const { RP3D_PROFILE ( " " , mProfiler ) ; const Vector3 pq = ray . point2 - ray . point1 ; const Vector3 pa = mPoints [ 0 ] - ray . point1 ; const Vector3 pb = mPoints [ 1 ] - ray . point1 ; const Vector3 pc = mPoints [ 2 ] - ray . point1 ; const Vector3 m = pq . cross ( pc ) ; decimal u = pb . dot ( m ) ; if ( mRaycastTestType == TriangleRaycastSide :: FRONT ) { if ( u < decimal ( 0.0 ) ) return false ; } else if ( mRaycastTestType == TriangleRaycastSide :: BACK ) { if ( u > decimal ( 0.0 ) ) return false ; } decimal v = - pa . dot ( m ) ; if ( mRaycastTestType == TriangleRaycastSide :: FRONT ) { if ( v < decimal ( 0.0 ) ) return false ; } else if ( mRaycastTestType == TriangleRaycastSide :: BACK ) { if ( v > decimal ( 0.0 ) ) return false ; } else if ( mRaycastTestType == TriangleRaycastSide :: FRONT_AND_BACK ) { if ( ! sameSign ( u , v ) ) return false ; } decimal w = pa . dot ( pq . cross ( pb ) ) ; if ( mRaycastTestType == TriangleRaycastSide :: FRONT ) { if ( w < decimal ( 0.0 ) ) return false ; } else if ( mRaycastTestType == TriangleRaycastSide :: BACK ) { if ( w > decimal ( 0.0 ) ) return false ; } else if ( mRaycastTestType == TriangleRaycastSide :: FRONT_AND_BACK ) { if ( ! sameSign ( u , w ) ) return false ; } if ( approxEqual ( u , 0 ) && approxEqual ( v , 0 ) && approxEqual ( w , 0 ) ) return false ; decimal denom = decimal ( 1.0 ) / ( u + v + w ) ; u *= denom ; v *= denom ; w *= denom ; const Vector3 localHitPoint = u * mPoints [ 0 ] + v * mPoints [ 1 ] + w * mPoints [ 2 ] ; const decimal hitFraction = ( localHitPoint - ray . point1 ) . length ( ) / pq . length ( ) ; if ( hitFraction < decimal ( 0.0 ) || hitFraction > ray . maxFraction ) return false ; Vector3 normal = ( mPoints [ 1 ] - mPoints [ 0 ] ) . cross ( mPoints [ 2 ] - mPoints [ 0 ] ) ; normal . normalize ( ) ; normal = normal . dot ( pq ) > decimal ( 0.0 ) ? - normal : normal ; raycastInfo . body = collider -> getBody ( ) ; raycastInfo . collider = collider ; raycastInfo . worldPoint = localHitPoint ; raycastInfo . hitFraction = hitFraction ; raycastInfo . worldNormal = normal ; return true ; }
Raycast method with feedback information
This method use the line vs triangle raycasting technique described in
Real-time Collision Detection by Christer Ericson.
Raycast method with feedback information This method use the line vs triangle raycasting technique described in Real - time Collision Detection by Christer Ericson .
/*allocator*/ // Test if the line PQ is inside the eges BC, CA and AB. We use the triple // product for this test. // If the line PQ is in the triangle plane (case where u=v=w=0) // Compute the barycentric coordinates (u, v, w) to determine the // intersection point R, R = u * a + v * b + w * c // Compute the local hit point using the barycentric coordinates // Compute the triangle face normal