Fixed the original ray-sphere intersection

Changed the original analytic method to a geometrical.

The errors in the original intersection calculation:
The function has a sphere center parameter, but ignores it and assumes
that the sphere is in the origo.
It calculates the length of the ray direction vector, but later on uses
this vector as a unit vector.
The position calculation is simply wrong. It multiplies the direction
vector with the radius of the sphere instead of the calculated
intersection distance.

The quadratic equation solving could be improved too:
There should be an early exit for negative discriminant.
The naive implementation sould be changed to a floating-point
specialized one.
This commit is contained in:
boromisp 2012-11-11 23:41:11 +01:00
parent 3a3c1fd8e8
commit ed12134f34
2 changed files with 10 additions and 25 deletions

View File

@ -81,9 +81,9 @@ namespace glm
//! From GLM_GTX_intersect extension. //! From GLM_GTX_intersect extension.
template <typename genType> template <typename genType>
bool intersectRaySphere( bool intersectRaySphere(
genType const & orig, genType const & dir, genType const & rayStarting, genType const & rayNormalizedDirection,
genType const & center, typename genType::value_type radius, genType const & sphereCenter, const typename genType::value_type sphereRadius,
genType & position, genType & normal); genType & intersectionPosition, genType & intersectionNormal);
//! Compute the intersection of a line and a sphere. //! Compute the intersection of a line and a sphere.
//! From GLM_GTX_intersect extension //! From GLM_GTX_intersect extension

View File

@ -151,31 +151,16 @@ namespace glm
template <typename genType> template <typename genType>
GLM_FUNC_QUALIFIER bool intersectRaySphere GLM_FUNC_QUALIFIER bool intersectRaySphere
( (
genType const & rayStarting, genType const & rayDirection, genType const & rayStarting, genType const & rayNormalizedDirection,
genType const & sphereCenter, typename genType::value_type sphereRadius, genType const & sphereCenter, const typename genType::value_type sphereRadius,
genType & position, genType & normal genType & intersectionPosition, genType & intersectionNormal
) )
{ {
typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); typename genType::value_type distance;
if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) )
typename genType::value_type a = dot(rayDirection, rayDirection);
typename genType::value_type b = typename genType::value_type(2) * dot(rayStarting, rayDirection);
typename genType::value_type c = dot(rayStarting, rayStarting) - sphereRadius * sphereRadius;
typename genType::value_type d = b * b - typename genType::value_type(4) * a * c;
typename genType::value_type e = sqrt(d);
typename genType::value_type x1 = (-b - e) / (typename genType::value_type(2) * a);
typename genType::value_type x2 = (-b + e) / (typename genType::value_type(2) * a);
if(x1 > Epsilon)
{ {
position = rayStarting + rayDirection * sphereRadius; intersectionPosition = rayStarting + rayNormalizedDirection * distance;
normal = (position - sphereCenter) / sphereRadius; intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius;
return true;
}
else if(x2 > Epsilon)
{
position = rayStarting + rayDirection * sphereRadius;
normal = (position - sphereCenter) / sphereRadius;
return true; return true;
} }
return false; return false;