/// Implementation derived from Wild Magic (Version 2) Software Library, available /// from http://www.geometrictools.com/Downloads/WildMagic2p5.zip under free license int SpherePrimitiveEvaluator::intersectionPoints( const Imath::V3f &origin, const Imath::V3f &direction, std::vector<PrimitiveEvaluator::ResultPtr> &results, float maxDistance ) const { results.clear(); Imath::V3f dir = direction.normalized(); (void)direction; float a0 = origin.dot(origin) - m_sphere->radius() * m_sphere->radius(); float a1 = dir.dot( origin ); float discr = a1 * a1 - a0; if (discr < 0.0) { return 0; } if ( discr >= Imath::limits<float>::epsilon() ) { float root = sqrt( discr ); float t0 = -a1 - root; if ( t0 >= 0.0 ) { Imath::V3f p0 = origin + t0 * dir; if ( (origin - p0).length() < maxDistance ) { ResultPtr r = staticPointerCast< Result > ( createResult() ); r->m_p = p0; results.push_back( r ); } } float t1 = -a1 + root; if ( t1 >= 0.0 ) { Imath::V3f p1 = origin + t1 * dir; if ( (origin - p1).length() < maxDistance ) { ResultPtr r = staticPointerCast< Result > ( createResult() ); r->m_p = p1; results.push_back( r ); } } } else { float t = -a1; if ( t >= 0.0 ) { Imath::V3f p = origin + t * dir; if ( (origin - p).length() < maxDistance ) { ResultPtr r = staticPointerCast< Result > ( createResult() ); r->m_p = p; results.push_back( r ); } } } assert( results.size() >= 0 ); assert( results.size() <= 2 ); return results.size(); }
/// Implementation derived from Wild Magic (Version 2) Software Library, available /// from http://www.geometrictools.com/Downloads/WildMagic2p5.zip under free license bool SpherePrimitiveEvaluator::intersectionPoint( const Imath::V3f &origin, const Imath::V3f &direction, PrimitiveEvaluator::Result *result, float maxDistance ) const { assert( dynamic_cast<Result *>( result ) ); Result *sr = static_cast<Result *>( result ); Imath::V3f dir = direction.normalized(); (void)direction; float a0 = origin.dot( origin ) - m_sphere->radius() * m_sphere->radius(); float a1 = dir.dot( origin ); float discr = a1 * a1 - a0; if (discr < 0.0) { return false; } if ( discr >= Imath::limits<float>::epsilon() ) { float root = sqrt( discr ); float t0 = -a1 - root; float t1 = -a1 + root; Imath::V3f p0 = origin + t0 * dir; Imath::V3f p1 = origin + t1 * dir; if ( t0 >= 0.0 ) { if ( t1 >= 0.0 ) { if ( (origin - p0).length2() < ( origin - p1 ).length2() ) { sr->m_p = p0; } else { sr->m_p = p1; } } else { sr->m_p = p0; } } else if ( t1 >= 0.0 ) { sr->m_p = p1; } else { return false; } } else { float t = -a1; if ( t >= 0.0 ) { sr->m_p = origin + t * dir; } else { return false; } } if ( (sr->m_p - origin).length() < maxDistance) { return true; } return false; }