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