1 /*
2  * VMMLib - Intersection classes
3  *
4  * @author Jafet Villafranca
5  *
6  * Implements ray-object intersection, storing the ray parameters as attributes
7  * and implementing intersection tests against different types of objects
8  * (e.g. sphere)
9  *
10  */
11 
12 #ifndef __VMML__INTERSECTION__HPP__
13 #define __VMML__INTERSECTION__HPP__
14 
15 #include <vmmlib/vector.hpp>
16 
17 namespace vmml
18 {
19 template< typename T > class intersection
20 {
21 public:
22     typedef vector< 3, T >    vec3;
23     typedef vector< 4, T >    vec4;
24 
25     /**
26       Constructors
27 
28       @param[in]    origin      Ray origin
29       @param[in]    direction   Ray direction
30      */
intersection(const vec3 & origin,const vec3 & direction)31     intersection( const vec3& origin, const vec3& direction )
32         : _origin ( origin )
33         , _direction ( vmml::normalize( direction ))
34     {}
~intersection()35     ~intersection() {}
36 
37     /**
38       Ray Sphere Intersection - Optimized solution
39       "Real-time Rendering 3rd Edition"
40 
41       @param[in]    center      Sphere center
42       @param[in]    radius      Sphere radius
43       @param[out]   t           Intersection distance
44 
45       @return Whether the ray intersects the sphere
46      */
47     bool test_sphere( const vec4& sphere, T& t ) const;
48 
49 private:
50     const vec3 _origin;
51     const vec3 _direction;
52 
53 }; // class intersection
54 
55 
56 template< typename T >
57 bool
test_sphere(const vec4 & sphere,T & t) const58 intersection< T >::test_sphere( const vec4& sphere, T& t ) const
59 {
60     const vec3 center = vec3(sphere.x(), sphere.y(), sphere.z());
61     const T radius = sphere.w();
62 
63     const vec3 centerVec = center - _origin;
64     const T vecProjection = centerVec.dot(_direction);
65 
66     const T sqDistance = centerVec.squared_length();
67     const T sqRadius = radius * radius;
68 
69     /** Sphere behind the ray origin and ray origin outside the sphere */
70     if( vecProjection < 0 && sqDistance > sqRadius )
71         return false;
72 
73     /** Squared distance from sphere center to the projection */
74     const T sqCenterToProj = sqDistance - vecProjection * vecProjection;
75 
76     if( sqCenterToProj > sqRadius )
77         return false;
78 
79     /** Distance from the sphere center to the surface along the ray direction*/
80     const T distSurface = sqrt( sqRadius - sqCenterToProj );
81 
82     if(sqDistance > sqRadius)
83         t = vecProjection - distSurface;
84     else
85         t = vecProjection + distSurface;
86 
87     return true;
88 }
89 
90 
91 } // namespace vmml
92 
93 #endif
94