Merge pull request #10 from boromisp/master

Sphere intersection fixes
This commit is contained in:
Christophe Riccio 2012-11-13 08:51:21 -08:00
commit 63ae274be2
2 changed files with 57 additions and 47 deletions

View File

@ -68,21 +68,31 @@ namespace glm
genType const & vert0, genType const & vert1, genType const & vert2, genType const & vert0, genType const & vert1, genType const & vert2,
genType & position); genType & position);
//! Compute the intersection distance of a ray and a sphere.
//! The ray direction vector is unit length.
//! From GLM_GTX_intersect extension.
template <typename genType>
bool intersectRaySphere(
genType const & rayStarting, genType const & rayNormalizedDirection,
genType const & sphereCenter, const typename genType::value_type sphereRadiusSquered,
typename genType::value_type & intersectionDistance);
//! Compute the intersection of a ray and a sphere. //! Compute the intersection of a ray and a sphere.
//! 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
template <typename genType> template <typename genType>
bool intersectLineSphere( bool intersectLineSphere(
genType const & point0, genType const & point1, genType const & point0, genType const & point1,
genType const & center, typename genType::value_type radius, genType const & sphereCenter, typename genType::value_type sphereRadius,
genType & position, genType & normal); genType & intersectionPosition1, genType & intersectionNormal1,
genType & intersectionPosition2 = genType(), genType & intersectionNormal2 = genType());
/// @} /// @}
}//namespace glm }//namespace glm

View File

@ -130,31 +130,37 @@ 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 sphereRadiusSquered,
genType & position, genType & normal typename genType::value_type & intersectionDistance
) )
{ {
typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
genType diff = sphereCenter - rayStarting;
typename genType::value_type a = dot(rayDirection, rayDirection); typename genType::value_type t0 = dot(diff, rayNormalizedDirection);
typename genType::value_type b = typename genType::value_type(2) * dot(rayStarting, rayDirection); typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
typename genType::value_type c = dot(rayStarting, rayStarting) - sphereRadius * sphereRadius; if( dSquared > sphereRadiusSquered )
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; return false;
normal = (position - sphereCenter) / sphereRadius;
return true;
} }
else if(x2 > Epsilon) typename genType::value_type t1 = sqrt( sphereRadiusSquered - dSquared );
intersectionDistance = t0 > t1 + Epsilon ? t0 - t1 : t0 + t1;
return intersectionDistance > Epsilon;
}
template <typename genType>
GLM_FUNC_QUALIFIER bool intersectRaySphere
(
genType const & rayStarting, genType const & rayNormalizedDirection,
genType const & sphereCenter, const typename genType::value_type sphereRadius,
genType & intersectionPosition, genType & intersectionNormal
)
{ {
position = rayStarting + rayDirection * sphereRadius; typename genType::value_type distance;
normal = (position - sphereCenter) / sphereRadius; if( intersectRaySphere( rayStarting, rayNormalizedDirection, sphereCenter, sphereRadius * sphereRadius, distance ) )
{
intersectionPosition = rayStarting + rayNormalizedDirection * distance;
intersectionNormal = (intersectionPosition - sphereCenter) / sphereRadius;
return true; return true;
} }
return false; return false;
@ -164,33 +170,27 @@ namespace glm
GLM_FUNC_QUALIFIER bool intersectLineSphere GLM_FUNC_QUALIFIER bool intersectLineSphere
( (
genType const & point0, genType const & point1, genType const & point0, genType const & point1,
genType const & center, typename genType::value_type radius, genType const & sphereCenter, typename genType::value_type sphereRadius,
genType & position, genType & normal genType & intersectionPoint1, genType & intersectionNormal1,
genType & intersectionPoint2, genType & intersectionNormal2
) )
{ {
typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon(); typename genType::value_type Epsilon = std::numeric_limits<typename genType::value_type>::epsilon();
genType dir = normalize(point1 - point0);
genType dir = point1 - point0; genType diff = sphereCenter - point0;
typename genType::value_type a = dot(dir, dir); typename genType::value_type t0 = dot(diff, dir);
typename genType::value_type b = typename genType::value_type(2) * dot(center, dir); typename genType::value_type dSquared = dot(diff, diff) - t0 * t0;
typename genType::value_type c = dot(center, center) - radius * radius; if( dSquared > 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 = center + dir * radius;
normal = (position - center) / radius;
return true;
}
else if(x2 > Epsilon)
{
position = center + dir * radius;
normal = (position - center) / radius;
return true;
}
return false; return false;
} }
typename genType::value_type t1 = sqrt( sphereRadius * sphereRadius - dSquared );
if( t0 < t1 + Epsilon )
t1 = -t1;
intersectionPoint1 = point0 + dir * (t0 - t1);
intersectionNormal1 = (intersectionPoint1 - sphereCenter) / sphereRadius;
intersectionPoint2 = point0 + dir * (t0 + t1);
intersectionNormal2 = (intersectionPoint2 - sphereCenter) / sphereRadius;
return true;
}
}//namespace glm }//namespace glm