library of assembled shared sources

http://lass.cocamware.com

ray_3d_sphere_3d.h

Go to the documentation of this file.
00001 /** @file
00002  *  @author Bram de Greve (bramz@users.sourceforge.net)
00003  *  @author Tom De Muer (tomdemuer@users.sourceforge.net)
00004  *
00005  *  *** BEGIN LICENSE INFORMATION ***
00006  *  
00007  *  The contents of this file are subject to the Common Public Attribution License 
00008  *  Version 1.0 (the "License"); you may not use this file except in compliance with 
00009  *  the License. You may obtain a copy of the License at 
00010  *  http://lass.sourceforge.net/cpal-license. The License is based on the 
00011  *  Mozilla Public License Version 1.1 but Sections 14 and 15 have been added to cover 
00012  *  use of software over a computer network and provide for limited attribution for 
00013  *  the Original Developer. In addition, Exhibit A has been modified to be consistent 
00014  *  with Exhibit B.
00015  *  
00016  *  Software distributed under the License is distributed on an "AS IS" basis, WITHOUT 
00017  *  WARRANTY OF ANY KIND, either express or implied. See the License for the specific 
00018  *  language governing rights and limitations under the License.
00019  *  
00020  *  The Original Code is LASS - Library of Assembled Shared Sources.
00021  *  
00022  *  The Initial Developer of the Original Code is Bram de Greve and Tom De Muer.
00023  *  The Original Developer is the Initial Developer.
00024  *  
00025  *  All portions of the code written by the Initial Developer are:
00026  *  Copyright (C) 2004-2007 the Initial Developer.
00027  *  All Rights Reserved.
00028  *  
00029  *  Contributor(s):
00030  *
00031  *  Alternatively, the contents of this file may be used under the terms of the 
00032  *  GNU General Public License Version 2 or later (the GPL), in which case the 
00033  *  provisions of GPL are applicable instead of those above.  If you wish to allow use
00034  *  of your version of this file only under the terms of the GPL and not to allow 
00035  *  others to use your version of this file under the CPAL, indicate your decision by 
00036  *  deleting the provisions above and replace them with the notice and other 
00037  *  provisions required by the GPL License. If you do not delete the provisions above,
00038  *  a recipient may use your version of this file under either the CPAL or the GPL.
00039  *  
00040  *  *** END LICENSE INFORMATION ***
00041  */
00042 
00043 #ifndef LASS_GUARDIAN_OF_INCLUSION_PRIM_RAY_3D_SPHERE_3D_H
00044 #define LASS_GUARDIAN_OF_INCLUSION_PRIM_RAY_3D_SPHERE_3D_H
00045 
00046 #include "prim_common.h"
00047 #include "ray_3d.h"
00048 #include "sphere_3d.h"
00049 #include "../num/basic_ops.h"
00050 #include "../num/floating_point_consistency.h"
00051 
00052 namespace lass
00053 {
00054 namespace prim
00055 {
00056 
00057 namespace impl
00058 {
00059     /** @internal
00060      */
00061     template <class NormalizingPolicy>
00062     struct RaySphere
00063     {
00064         template <typename T, class PP>
00065         static Result intersect(
00066                 const Sphere3D<T>& sphere, const Ray3D<T, NormalizingPolicy, PP>& ray, 
00067                 T& t, const T& tMin)
00068         {
00069             typedef Vector3D<T> TVector;
00070             typedef typename TVector::TValue TValue;
00071             typedef typename TVector::TNumTraits TNumTraits;
00072             typedef num::Consistent<T> TConsistent;
00073 
00074             const TVector cs = ray.support() - sphere.center();
00075 
00076             // atē + bt + c == 0
00077             const TValue a = ray.direction().squaredNorm();
00078             const TValue b = dot(cs, ray.direction());
00079             const TValue c = cs.squaredNorm() - num::sqr(sphere.radius());
00080 
00081             const TValue discriminant = num::sqr(b) - a * c;
00082 
00083             if (discriminant > TNumTraits::zero)
00084             {
00085                 const TValue sqrtD = num::sqrt(discriminant);
00086                 const TValue invA = num::inv(a);
00087                 const TConsistent t1 = (-b - sqrtD) * invA;
00088                 if (t1 > tMin)
00089                 {
00090                     t = t1.value();
00091                     return rOne;
00092                 }
00093                 const TConsistent t2 = (-b + sqrtD) * invA;
00094                 if (t2 > tMin)
00095                 {
00096                     t = t2.value();
00097                     return rOne;
00098                 }
00099             }
00100             else if (discriminant == TNumTraits::zero)
00101             {
00102                 const TConsistent t1 = -b / a;
00103                 if (t1 > tMin)
00104                 {
00105                     t = t1.value();
00106                     return rOne;
00107                 }
00108             }
00109             return rNone;
00110         }
00111     };
00112 
00113     /** @internal
00114      */
00115     template <>
00116     struct RaySphere<Normalized>
00117     {
00118         template <typename T, class PP>
00119         static Result intersect(const Sphere3D<T>& sphere, 
00120                                 const Ray3D<T, Normalized, PP>& ray, 
00121                                 T& t, const T& tMin)
00122         {
00123             typedef Vector3D<T> TVector;
00124             typedef typename TVector::TValue TValue;
00125             typedef typename TVector::TNumTraits TNumTraits;
00126             typedef num::Consistent<T> TConsistent;
00127 
00128             typedef typename num::DoublePrecision<T>::Type TDouble;
00129             typedef Vector3D<TDouble> TVectorDouble;
00130 
00131             const TVectorDouble cs(ray.support() - sphere.center());
00132 
00133             // atē + bt + c == 0
00134             //const TValue a = 1;
00135             const TDouble b = dot(cs, TVectorDouble(ray.direction()));
00136             const TDouble c = cs.squaredNorm() - num::sqr(TDouble(sphere.radius()));
00137 
00138             const TDouble discriminant = num::sqr(b) - c;
00139 
00140             if (discriminant > TNumTraits::zero)
00141             {
00142                 const TDouble sqrtD = num::sqrt(discriminant);
00143                 const TConsistent t1 = static_cast<TValue>(-b - sqrtD);
00144                 if (t1 > tMin)
00145                 {
00146                     t = t1.value();
00147                     return rOne;
00148                 }
00149                 const TConsistent t2 = static_cast<TValue>(-b + sqrtD);
00150                 if (t2 > tMin)
00151                 {
00152                     t = t2.value();
00153                     return rOne;
00154                 }
00155             }
00156             else if (discriminant == TNumTraits::zero)
00157             {
00158                 const TConsistent t1 = static_cast<TValue>(-b);
00159                 if (t1 > tMin)
00160                 {
00161                     t = t1.value();
00162                     return rOne;
00163                 }
00164             }
00165             return rNone;
00166         }
00167     };
00168 }
00169 
00170 
00171 
00172 
00173 /** Find the intersection of a ray and a sphere by their parameter t on the ray.
00174  *  @relates lass::prim::Ray3D
00175  *  @relates lass::prim:Sphere3D
00176  *
00177  *  @param sphere [in] the sphere
00178  *  @param ray [in] the ray
00179  *  @param t [out] the parameter of the intersection point > @a tMin.
00180  *  @param tMin [in] the minimum t that may be returned as valid intersection.
00181  *  @return @arg rNone      no intersections with @a t > @a tMin found
00182  *                          @a t is not assigned.
00183  *          @arg rOne       a intersection with @a t > @a tMin is found
00184  *                          @a t is assigned.
00185  *
00186  *  http://flipcode.dxbug.com/wiki/index.php?title=Line-Sphere_%28Collision%29
00187  */
00188 template<typename T, class NP, class PP> inline
00189 Result intersect(
00190         const Sphere3D<T>& sphere, const Ray3D<T, NP, PP>& ray, 
00191         T& t, const T& tMin = T())
00192 {
00193 #ifdef NDEBUG
00194     return impl::RaySphere<NP>::intersect(sphere, ray, t, tMin);
00195 #else
00196     const Result result = impl::RaySphere<NP>::intersect(sphere, ray, t, tMin);
00197     LASS_ASSERT(t > tMin || result == rNone);
00198     return result;
00199 #endif
00200 }
00201 
00202 }
00203 }
00204 
00205 #endif
00206 
00207 // EOF

Generated on Mon Nov 10 14:21:21 2008 for Library of Assembled Shared Sources by doxygen 1.5.7.1
SourceForge.net Logo