// P - source point, A - direction // C - sphere center, R - radius bool IntersectRayToSphere( const LVector3& P, const LVector3& A, const LVector3& C, float R ) { float t = -( P.Dot( A ) - A.Dot( C ) ) / A.Dot( A ); LVector3 v = P + A * t - C; return ( v.Dot( v ) <= R * R ); }
bool IntersectRayToPlane( const LVector3& P, const LVector3& A, const LVector3& N, float D, LVector3& isect ) { float denom = A.Dot( N ); if ( fabs( denom ) < 0.0001f ) { return false; } float t = -( D + P.Dot( N ) ) / denom; isect = P + A * t; return true; }
bool IntersectRayToBox( const LVector3& P, const LVector3& A, const LVector3& Pos, LVector3* V, const LVector3& Size, LVector3& isect ) { float Sign[] = { -1, -1, -1, +1, +1, +1 }; // distance to source point; float _dist = -1.0f; bool Intersection = false; // check six faces for ( int i = 0 ; i < 6 ; i++ ) { LVector3 Pt = Sign[i] * V[i % 3] * Size[i % 3] * 0.5f; LVector3 N = Pt.GetNormalized(); Pt = P + Pt; float D = N.Dot( Pt ); LVector3 LocalISect; if ( IntersectRayToPlane( P, A, N, D, LocalISect ) ) { // plane vectors LVector3 V1 = V[( i+1 )%3]; LVector3 V2 = V[( i+2 )%3]; float szX = Size[( i+1 )%3]; float szY = Size[( i+2 )%3]; // project to plane float x = ( LocalISect - Pt ).Dot( V1 ); float y = ( LocalISect - Pt ).Dot( V2 ); // check if the point is inside the rectangle if ( x > -szX / 2 && x < szX / 2 && y > -szY / 2 && y < szY / 2 ) { Intersection = true; // it is, compare its distance to P - to select the closest one float _newDist = ( isect - P ).Length(); if ( _dist < 0.0f || _newDist < _dist ) { isect = LocalISect; _dist = _newDist; } } } } return Intersection; }
// old Pascal source ... bool ClosestPointsOnLines( const LVector3& Pt1, const LVector3& Dir1, const LVector3& Pt2, const LVector3& Dir2, float& t1, float& t2 ) { float C0, C1; float a11, a12, a21, a22; float det1, detA, detB; C0 = ( Pt2 - Pt1 ).Dot( Dir1 ); C1 = ( Pt2 - Pt1 ).Dot( Dir2 ); a11 = +Dir1.Dot( Dir1 ); a12 = -Dir1.Dot( Dir2 ); a21 = -a12; a22 = -Dir2.Dot( Dir2 ); det1 = a11 * a22 - a21 * a12; FIXME( "perform approximate IsZero() check" ) if ( det1 != 0.0f ) { detA = C0 * a22 - C1 * a12; detB = a11 * C1 - a21 * C0; t1 = detA / det1; t2 = detB / det1; return true; } // no single point , but we just give a required pair t1 = C0 / a11; t2 = 0; return false; }
bool IntersectRayToTriangle( const LVector3& P, const LVector3& A, const LVector3& V1, const LVector3& V2, const LVector3& V3, LVector3& isect ) { LVector3 N = ( V3 - V2 ).Cross( V2 - V1 ); if ( !IntersectRayToPlane( P, A, N , -N.Dot( V1 ), isect ) ) { return false; } // try cross products LVector3 l1 = V1 - isect; LVector3 l2 = V2 - isect; LVector3 l3 = V3 - isect; float lam1 = ( l1 ).Cross( l2 ).Dot( N ); float lam2 = ( l2 ).Cross( l3 ).Dot( N ); float lam3 = ( l3 ).Cross( l1 ).Dot( N ); // unnormalized barycentric coordinates must be of the same sign (the sign depends on N's direction and does not matter) return ( ( lam1 < 0 && lam2 < 0 && lam3 < 0 ) || ( lam1 > 0 && lam2 > 0 && lam3 > 0 ) ); }