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