TAPs 0.7.7.3
TAPsCGMath.cpp
Go to the documentation of this file.
00001 /******************************************************************************
00002 TAPsCGMath.cpp
00003 ******************************************************************************/
00009 /******************************************************************************
00010 SUKITTI PUNAK   (07/27/2005)
00011 UPDATE          (10/26/2010)
00012 ******************************************************************************/
00013 #include "TAPsCGMath.hpp"
00014 // Using Inclusion Model (i.e. definitions are included in declarations)
00015 //                       (this name.cpp is included in name.hpp)
00016 // Each friend is defined directly inside its declaration.
00017 
00018 BEGIN_NAMESPACE_TAPs
00019 //=============================================================================
00020 // Constant Values
00021 //=============================================================================
00022 template <typename T> const Vector3<T> CGMath<T>::ZeroVector( 0, 0, 0 );
00023 template <typename T> const Vector3<T> CGMath<T>::VectorX( 1, 0, 0 );
00024 template <typename T> const Vector3<T> CGMath<T>::VectorY( 0, 1, 0 );
00025 template <typename T> const Vector3<T> CGMath<T>::VectorZ( 0, 0, 1 );
00026 template <typename T> const Matrix3x3<T> CGMath<T>::IdentityMatrix3x3( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
00027 template <typename T> const Matrix4x4<T> CGMath<T>::IdentityMatrix4x4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
00028 //
00029 template <typename T> Vector3<T>    CGMath<T>::TempVector3( 0, 0, 0 );
00030 template <typename T> Vector3<T>    CGMath<T>::TempVector4( 0, 0, 0, 1 );
00031 template <typename T> Matrix3x3<T>  CGMath<T>::TempMatrix3x3( 1, 0, 0, 0, 1, 0, 0, 0, 1 );
00032 template <typename T> Matrix4x4<T>  CGMath<T>::TempMatrix4x4( 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1 );
00033 //-----------------------------------------------------------------------------
00034 #ifndef _WINDOWS_
00035 #endif
00036 //-----------------------------------------------------------------------------
00037 
00038 //=========================================================================
00039 // Creating Matrices for transformations
00040 //-------------------------------------------------------------------------
00042 template <typename T>
00043 Matrix4x4<T> CGMath<T>::MatrixTranslation ( Vector3<T> const & translation )
00044 {
00045     return Matrix4x4<T>(
00046         1, 0, 0, translation[0],
00047         0, 1, 0, translation[1],
00048         0, 0, 1, translation[2],
00049         0, 0, 0, 1 );
00050 }
00051 
00053 template <typename T>
00054 Matrix4x4<T> CGMath<T>::MatrixRotation ( Quaternion<T> const & orientation )
00055 {
00056     return orientation.GetRotationMatrix4x4();
00057 }
00058 
00060 template <typename T>
00061 Matrix4x4<T> CGMath<T>::MatrixScale ( Vector3<T> const & scale )
00062 {
00063     return Matrix4x4<T>(
00064         scale[0],  0,      0,      0,
00065            0,   scale[1],  0,      0,
00066            0,      0,   scale[2],  0,
00067            0,      0,      0,      1 );
00068 }
00069 //-------------------------------------------------------------------------
00070 //=========================================================================
00071 
00072 
00073 
00074 
00075 //=============================================================================
00076 // Normal Calculation Fns
00077 //-----------------------------------------------------------------------------
00078 //-----------------------------------------------------------------------------
00079 // Normal Calculation Fns
00080 //=============================================================================
00081 
00082 
00083 
00084 
00085 //=============================================================================
00086 // Transformation Fns
00087 //-----------------------------------------------------------------------------
00088 // FN:  CreateRotationMatrix3x3 ()
00089 // DESC:    Find a 3x3 rotation matrix from given rotation axis and angle
00090 // I/P:  (Vector3<T>)   rotationAxis        a rotation axis
00091 // I/P:  (T)            rotationAngle       a rotation angle (in degrees)
00092 // O/P:  (Matrix3x3<T>) rotationMat         a 3x3 rotation matrix
00093 // From Mathematatics for 3D Game Programming & Computer Graphics (2nd ed)
00094 // The 3x3 rotation matrix is
00095 //               -                                               -
00096 //              |    c+(1-c)Ax^2   (1-c)AxAy-sAz   (1-c)AxAz+sAy  |
00097 // R_A(zeta) =  |  (1-c)AxAy+sAz     c+(1-c)Ay^2   (1-c)AyAz-sAx  |
00098 //              |  (1-c)AxAz-sAy   (1-c)AyAz+sAx     c+(1-c)Az^2  |
00099 //               -                                               -
00100 template <typename T>
00101 Matrix3x3<T> CGMath<T>::CreateRotationMatrix3x3 (
00102             Vector3<T> const &  rotationAxis,   // I/P: Rotation Axis
00103             T                   rotationAngle   // I/P: Rotation Angle (in degs)
00104 )
00105 {
00106     Vector3<T> A = rotationAxis.GetUnit();
00107     T rad = rotationAngle * Math<T>::DEG_TO_RAD;
00108     T c = cos( rad ), s = sin( rad );
00109     T c_1 = T(1.0) - c;
00110     T AxAy = A[0] * A[1];
00111     T AxAz = A[0] * A[2];
00112     T AyAz = A[1] * A[2];
00113     T sAx = s * A[0];
00114     T sAy = s * A[1];
00115     T sAz = s * A[2];
00116     //--------------------------------------------------------------------
00117     return Matrix3x3<T>( 
00118             c + c_1*A[0]*A[0],  c_1*AxAy - sAz,     c_1*AxAz + sAy,
00119             c_1*AxAy + sAz,     c + c_1*A[1]*A[1],  c_1*AyAz - sAx,
00120             c_1*AxAz - sAy,     c_1*AyAz + sAx,     c + c_1*A[2]*A[2] );
00121 }
00122 //-----------------------------------------------------------------------------
00123 template <typename T>
00124 Matrix4x4<T> CGMath<T>::CreateRotationMatrix4x4 (
00125             Vector3<T> const &  rotationAxis,   // I/P: Rotation Axis
00126             T                   rotationAngle   // I/P: Rotation Angle (in degs)
00127 )
00128 {
00129     Vector3<T> A = rotationAxis.GetUnit();
00130     T rad = rotationAngle * Math<T>::DEG_TO_RAD;
00131     T c = cos( rad ), s = sin( rad );
00132     T c_1 = T(1.0) - c;
00133     T AxAy = A[0] * A[1];
00134     T AxAz = A[0] * A[2];
00135     T AyAz = A[1] * A[2];
00136     T sAx = s * A[0];
00137     T sAy = s * A[1];
00138     T sAz = s * A[2];
00139     //--------------------------------------------------------------------
00140     return Matrix4x4<T>( 
00141             c + c_1*A[0]*A[0],  c_1*AxAy - sAz,     c_1*AxAz + sAy,     0,
00142             c_1*AxAy + sAz,     c + c_1*A[1]*A[1],  c_1*AyAz - sAx,     0,
00143             c_1*AxAz - sAy,     c_1*AyAz + sAx,     c + c_1*A[2]*A[2],  0,
00144             0,                  0,                  0,                  1
00145     );
00146 }
00147 //-----------------------------------------------------------------------------
00148 // FN:  CreateRotationMatrix3x3FromVectorAtoVectorB ()
00149 // DESC:    Find a 3x3 rotation matrix from given rotation axis and angle
00150 // I/P:  (Vector3<T>)   A               starting (vector) point
00151 // I/P:  (Vector3<T>)   B               ending (vector) point
00152 // O/P:  (Matrix3x3<T>) rotationMat     a 3x3 rotation matrix
00153 template <typename T>
00154 Matrix3x3<T> CGMath<T>::CreateRotationMatrix3x3FromVectorAtoVectorB (
00155             Vector3<T> const &  startingPt,     // I/P: starting point
00156             Vector3<T> const &  endingPt        // I/P: ending point
00157 )
00158 {
00159     Vector3<T> rotationAxis( startingPt ^ endingPt );
00160     T rotationAngle = acos((startingPt*endingPt)/startingPt.Length()/endingPt.Length())
00161                         * Math<T>::RAD_TO_DEG;
00162     return CreateRotationMatrix3x3( rotationAxis, rotationAngle );
00163 }
00164 //-----------------------------------------------------------------------------
00165 template <typename T>
00166 Matrix4x4<T> CGMath<T>::CreateRotationMatrix4x4FromVectorAtoVectorB (
00167             Vector3<T> const &  startingPt,     // I/P: starting point
00168             Vector3<T> const &  endingPt        // I/P: ending point
00169 )
00170 {
00171     Vector3<T> rotationAxis( startingPt ^ endingPt );
00172     T rotationAngle = acos((startingPt*endingPt)/startingPt.Length()/endingPt.Length())
00173                         * Math<T>::RAD_TO_DEG;
00174     return CreateRotationMatrix4x4( rotationAxis, rotationAngle );
00175 }
00176 //-----------------------------------------------------------------------------
00177 //=============================================================================
00178 
00179 //=============================================================================
00180 // Matrix Fns
00181 //=============================================================================
00182 //-----------------------------------------------------------------------------
00183 // FN:  EigValsVecsOf3x3SymMatrix ()
00184 // DESC:    Find eigen vectors of a 3x3 symmetric matrix.
00185 //          symmetric matrix always has all real eigen values 
00186 //          and its eigen vectors are orthogonal to one another.
00187 //          It also implies the matrix has its inverse matrix.
00188 // First solve for eigen values by using root finding
00189 //   a*x^3 + b*x^2 + c*x + d = 0;
00190 //   The formula is adapted from "Mathematical Handbook of Formulas and Tables"
00191 // Then inverse matrices for finding eigen values
00192 // I/P:  (Matrix3x3<T>) iM                      a 3x3 real symmetric matrix
00193 // O/P:  (T)            lamda1, lamda2, lamda3  eigen values
00194 // O/P:  (Vector3<T>)   v1, v2, v3              eigen vectors
00195 template <typename T>
00196 void CGMath<T>::EigValsVecsOf3x3SymMatrix (
00197             Matrix3x3<T> & iM,          // I/P: a 3x3 symmetric matrix
00198             T & l1,                     // O/P: first  eigen value
00199             T & l2,                     // O/P: second eigen value
00200             T & l3,                     // O/P: third  eigen value
00201             Vector3<T> & v1,            // O/P: first  eigen vector
00202             Vector3<T> & v2,            // O/P: second eigen vector
00203             Vector3<T> & v3             // O/P: third  eigen vector
00204 )
00205 {
00206     assert( iM.IsSymmetric() );
00207     //---------------------------------------------------------------
00208     // Find all three roots
00209     // Set up   a*x^3 + b*x^2 + c*x + d = 0
00210     //T a = 1;
00211     T b = -iM(0,0) - iM(1,1) - iM(2,2);
00212     T c =  iM(0,0)*iM(1,1) + iM(0,0)*iM(2,2) 
00213          - iM(0,1)*iM(0,1) + iM(1,1)*iM(2,2) 
00214          - iM(0,2)*iM(0,2) - iM(1,2)*iM(1,2);
00215     T d =  iM(0,2)*iM(0,2)*iM(1,1) 
00216          - iM(0,0)*iM(1,1)*iM(2,2) 
00217          - 2*iM(0,1)*iM(1,2)*iM(0,2) 
00218          + iM(0,1)*iM(0,1)*iM(2,2)
00219          + iM(0,0)*iM(1,2)*iM(1,2);
00220     //---------------------------------------------------------------
00221     // Calculate Discriminant
00222     //b /= a;  c /= a;  d /= a;
00223     T Q  = (T(3.0)*c - b*b) / T(9.0);
00224     T R  = (T(9.0)*b*c - T(27.0)*d - T(2.0)*b*b*b) / T(54.0);
00225     T Q3 = Q*Q*Q;
00226     T D  = Q3 + R*R;    // Discriminant
00227     //std::cout << "D: " << D << "\n";
00228     //---------------------------------------------------------------
00229     // All roots are real and unequal if D < 0.
00230     assert ( D < 0 );
00231     T zeta_3 = acos( R / sqrt(-Q3) ) / T(3.0);
00232     T sqrt2_Q = 2 * sqrt( -Q );
00233     T b_3 = b / T(3.0);
00234     l1 = sqrt2_Q * cos( zeta_3 ) - b_3;                         // root 1
00235     l2 = sqrt2_Q * cos( zeta_3 + T(2.0)/T(3.0)*Math<T>::PI ) - b_3; // root 2
00236     l3 = sqrt2_Q * cos( zeta_3 + T(4.0)/T(3.0)*Math<T>::PI ) - b_3; // root 3
00237     //---------------------------------------------------------------
00238     // Sorting the roots (eigen values) by their magnitude
00239     T temp;
00240     if ( fabs(l2) > fabs(l1) ) {            // l2 > l1
00241         temp = l1;  l1 = l2; l2 = temp;
00242         if ( fabs(l3) > fabs(l1) ) {        // l3 > l1
00243             temp = l1;  l1 = l3; l3 = temp;
00244         }
00245         else if ( fabs(l3) > fabs(l2) ) {   // l3 > l2
00246             temp = l2;  l2 = l3; l3 = temp;
00247         }
00248     }
00249     else {                                  // l1 > l2
00250         if ( fabs(l3) > fabs(l2) ) {
00251             temp = l2;  l2 = l3; l3 = temp; // l3 > l2
00252         }
00253     }
00254     assert( fabs(l1) >= fabs(l2) );
00255     assert( fabs(l2) >= fabs(l3) );
00256     //---------------------------------------------------------------
00257     // Find eigen vectors
00258     T a1,               b1 = iM(0,1),       c1 = iM(0,2);
00259     T a2 = iM(0,1),     b2,                 c2 = iM(1,2);
00260     T a3 = iM(0,2),     b3 = iM(1,2),       c3;
00261     T lamda[3] = { l1, l2, l3 };
00262     T divider;
00263     Vector3<T> v;
00264     for ( int i = 0; i < 3; ++i ) {
00265         a1 = iM(0,0) - lamda[i];
00266         b2 = iM(1,1) - lamda[i];
00267         c3 = iM(2,2) - lamda[i];
00268         divider = b2*a1 - b1*a2 - b3*a1 + b1*a3;
00269         
00270         //Matrix3x3<T> M( a1, b1, c1, a2, b2, c2, a3, b3, c3 );
00271         //assert( M.GetDeterminant() != 0 );
00272 
00273         // divider is zero when the determinant of the matrix is zero!
00274         //assert( divider != 0 );
00275         //----------------------------------------------------------------
00276         if ( divider != 0 ) {
00277         //if ( fabs(divider) > 1E-40 ) {
00278             v[0] = (b1*c2 - b2*c1 + b3*c1 - b1*c3) / divider;
00279             v[1] = (a2*c1 - a1*c2 - a3*c1 + a1*c3) / divider;
00280             v[2] = 1;
00281             //-------------------------------------------------------
00282             // make the vector a unit vector
00283             v.Normalized();
00284             //if ( divider == 0 )   {
00285             //  std::cout << divider << ": " << v << std::endl;
00286             //}
00287         }
00288         //----------------------------------------------------------------
00289         else {          // divider is near ZERO
00290             //assert( false );
00291             v.SetXYZ(0,0,0);
00292         }
00293         if      ( i == 0 )  v1 = v;     // 1st eigen vector
00294         else if ( i == 1 )  v2 = v;     // 2nd eigen vector
00295         else                v3 = v;     // 3rd eigen vector
00296     }
00297     //---------------------------------------------------------------
00298 }
00299 //-----------------------------------------------------------------------------
00300 //=============================================================================
00301 
00302 //=============================================================================
00303 // Intersection Finding
00304 //=============================================================================
00305 //-----------------------------------------------------------------------------
00306 //*****************************************************************************
00307 // FindRatioOfPointOnLineThatIntersectPlane
00308 // I/P: two vectors defining the line segment
00309 // I/P: a point followed by a point on the plane and its normal
00310 // O/P: the ratio of the point on the line that intersects the plane
00311 //      the ratio is [0-1] from l2 thru l1
00312 // O/P: the projected point on the line that intersects the plane
00313 //*****************************************************************************
00314 template <typename T>
00315 void CGMath<T>::FindRatioOfPointOnLineThatIntersectPlane ( 
00316                     Vector3<T> const & l1, Vector3<T> const & l2, // I/P: a line
00317                     Vector3<T> const & a,   // I/P: a point on the plane
00318                     Vector3<T> const & n,   // I/P: the plane (unit) normal
00319                     T &            ratio,   // O/P: the ratio
00320                     Vector3<T> &  projPt,   // O/P: the projected point
00321                     T tolerance 
00322 )
00323 {
00324     Vector3<T> l2l1( l2 - l1 );
00325     ratio  = (n*(a-l1)) / (n*l2l1);
00326     projPt = l1 + ratio*l2l1;
00327 }
00328 //-----------------------------------------------------------------------------
00329 
00330 
00331 //*****************************************************************************
00332 // Find the closest distance between two line segments
00333 //   First project p1 and p2 on the line Lq defined by q1 and q2.
00334 //     Let call them pq1 and pq2 respectively.
00335 //   Second project p2 on the plane defined by pq1 and the unit vector of Lq
00336 //     which is the plane normal.
00337 //     Let call the projected point pq3.
00338 //   Third determine d3, which is the square length of p1-pq3.
00339 //     If d3 is not zero, then the line segments are unparallel.
00340 //        Then find the closest points between the line segments.
00341 //          Let call the closest points ps and qs.
00342 //        Then the shortest distance is |ps - qs|.
00343 //     If d3 is zero, then the line segments are parallel.
00344 //        Then find the closest points between the line segments.
00345 //          In this case, there are four 
00346 //        Then the shortest distance is |ps - qs|.
00347 //*****************************************************************************
00348 template <typename T>
00349 void CGMath<T>::FindClosestDistanceBetweenTwoLineSegments ( 
00350                     Vector3<T> const & p1, Vector3<T> const & p2, // I/P: a line
00351                     Vector3<T> const & q1, Vector3<T> const & q2, // I/P: a line
00352                     T & distance,                   
00353                     Vector3<T> & Ncontact,          
00354                     T tolerance = Math<T>::ThresholdZero
00355 )
00356 {
00357     //---------------------------------------------------------------
00358     T k;
00359     Vector3<T> pq1, pq2, pq3;
00360     //---------------------------------------------------------------
00361     // Find the projected point (pq1) of p1 on the line defined by q2-q1
00362     FindProjectedPointOnALine( p1, q1, q2, k, pq1 );
00363     //---------------------------------------------------------------
00364     // Find the projected point (pq2) of p2 on the line defined by q2-q1
00365     FindProjectedPointOnALine( p2, q1, q2, k, pq2 );
00366     //---------------------------------------------------------------
00367     // Find the projected point (pq3) of p2 on the plane defined by the 
00368     //   point pq1 and the plane normal defined by (q2-q1)
00369     FindProjectedPointOnAPlane( p2, p1, (q2-q1).Normalized(), pq3 );
00370     //---------------------------------------------------------------
00371     T d3 = (p1 - pq3).SquaredLength();
00372     //---------------------------------------------------------------
00373     //---------------------------------------------------------------
00374     // Unparallel Case
00375     if ( d3 > tolerance ) {
00376         //std::cout << "Unparallel Case\n";
00377         Vector3<T> ps;
00378         Vector3<T> qs;
00379         T d1 = (p1 - pq1).SquaredLength();
00380         T d2 = (p2 - pq2).SquaredLength();
00381         k = ( d1 - d2 + d3 ) / d3 / static_cast<T>( 2.0 );
00382         if      ( k >= 1 )  ps = p2;
00383         else if ( k <= 0 )  ps = p1;
00384         else                ps = p1 + k*(p2-p1);
00385         FindProjectedPointOnALine( ps, q1, q2, k );
00386         if      ( k >= 1 )  qs = q2;
00387         else if ( k <= 0 )  qs = q1;
00388         else                qs = q1 + k*(q2-q1);
00389         Ncontact = qs - ps;
00390         distance = Ncontact.Length();
00391         Ncontact.Normalized();
00392     }
00393     //---------------------------------------------------------------
00394     // Parallel Case
00395     else {
00396         //std::cout << "Parallel Case\n";
00397         T k1;
00398         FindProjectedPointOnALine( p1, q1, q2, k1 );
00399         if ( 0 <= k1 && k1 <= 1 ) {
00400             //std::cout << "( 0 <= k1 && k1 <= 1 )\n";
00401             Vector3<T> q = q1 + k1*(q2-q1);
00402             Ncontact = q - p1;
00403             distance = Ncontact.Length();
00404             Ncontact.Normalized();
00405             return;
00406         }
00407         T k2;
00408         FindProjectedPointOnALine( p2, q1, q2, k2 );
00409         if ( 0 <= k2 && k2 <= 1 ) {
00410             //std::cout << "( 0 <= k2 && k2 <= 1 )\n";
00411             Vector3<T> q = q1 + k2*(q2-q1);
00412             Ncontact = q - p2;
00413             distance = Ncontact.Length();
00414             Ncontact.Normalized();
00415             return;
00416         }
00417         //std::cout << "k1: " << k1 << " k2: " << k2 << "\n";
00418         if ( fabs(k1) < fabs(k2) ) {
00419             //std::cout << "k1 < k2\n";
00420             T dist = (q1 - p1).SquaredLength();
00421             distance = (q1 - p2).SquaredLength();
00422             if ( dist < distance ) {
00423                 //std::cout << "(q1 - p1)\n";
00424                 distance = sqrt( dist );
00425                 Ncontact = (q1 - p1).Normalized();
00426                 return;
00427             }
00428             else {
00429                 //std::cout << "(q1 - p2)\n";
00430                 distance = sqrt( distance );
00431                 Ncontact = (q1 - p2).Normalized();
00432                 return;
00433             }
00434         }
00435         else {
00436             //std::cout << "k2 < k1\n";
00437             T dist = (q2 - p1).SquaredLength();
00438             distance = (q2 - p2).SquaredLength();
00439             if ( dist < distance ) {
00440                 //std::cout << "(q2 - p1)\n";
00441                 distance = sqrt( dist );
00442                 Ncontact = (q2 - p1).Normalized();
00443                 return;
00444             }
00445             else {
00446                 //std::cout << "(q2 - p2)\n";
00447                 distance = sqrt( distance );
00448                 Ncontact = (q2 - p2).Normalized();
00449                 return;
00450             }
00451         }
00452     }
00453     //---------------------------------------------------------------
00454 }
00455 //-----------------------------------------------------------------------------
00456 
00457 
00458 //*****************************************************************************
00459 // Find the closest distance between two line segments
00460 //   First project p1 and p2 on the line Lq defined by q1 and q2.
00461 //     Let call them pq1 and pq2 respectively.
00462 //   Second project p2 on the plane defined by pq1 and the unit vector of Lq
00463 //     which is the plane normal.
00464 //     Let call the projected point pq3.
00465 //   Third determine d3, which is the square length of p1-pq3.
00466 //     If d3 is not zero, then the line segments are unparallel.
00467 //        Then find the closest points between the line segments.
00468 //          Let call the closest points ps and qs.
00469 //        Then the shortest distance is |ps - qs|.
00470 //     If d3 is zero, then the line segments are parallel.
00471 //        Then find the closest points between the line segments.
00472 //          In this case, there are four 
00473 //        Then the shortest distance is |ps - qs|.
00474 //*****************************************************************************
00475 template <typename T>
00476 void CGMath<T>::FindClosestDistanceBetweenTwoLineSegments (
00477                     Vector3<T> const & p1, Vector3<T> const & p2, // I/P: a line 
00478                     Vector3<T> const & q1, Vector3<T> const & q2, // I/P: a line
00479                     T & distance,                   
00480                     Vector3<T> & Ncontact,          
00481                     Vector3<T> & projPtOnLine_1,    
00482                     Vector3<T> & projPtOnLine_2,    
00483                     T tolerance = Math<T>::ThresholdZero
00484 )
00485 {
00486     //---------------------------------------------------------------
00487     T k;
00488     Vector3<T> pq1, pq2, pq3;
00489     //---------------------------------------------------------------
00490     // Find the projected point (pq1) of p1 on the line defined by q2-q1
00491     FindProjectedPointOnALine( p1, q1, q2, k, pq1 );
00492     //---------------------------------------------------------------
00493     // Find the projected point (pq2) of p2 on the line defined by q2-q1
00494     FindProjectedPointOnALine( p2, q1, q2, k, pq2 );
00495     //---------------------------------------------------------------
00496     // Find the projected point (pq3) of p2 on the plane defined by the 
00497     //   point pq1 and the plane normal defined by (q2-q1)
00498     FindProjectedPointOnAPlane( p2, p1, (q2-q1).Normalized(), pq3 );
00499     //---------------------------------------------------------------
00500     T d3 = (p1 - pq3).SquaredLength();
00501     //---------------------------------------------------------------
00502     //---------------------------------------------------------------
00503     // Unparallel Case
00504     if ( d3 > tolerance ) {
00505         //std::cout << "Unparallel Case\n";
00506         T d1 = (p1 - pq1).SquaredLength();
00507         T d2 = (p2 - pq2).SquaredLength();
00508         k = ( d1 - d2 + d3 ) / d3 / static_cast<T>( 2.0 );
00509         if      ( k >= 1 )  projPtOnLine_1 = p2;
00510         else if ( k <= 0 )  projPtOnLine_1 = p1;
00511         else                projPtOnLine_1 = p1 + k*(p2-p1);
00512         FindProjectedPointOnALine( projPtOnLine_1, q1, q2, k );
00513         if      ( k >= 1 )  projPtOnLine_2 = q2;
00514         else if ( k <= 0 )  projPtOnLine_2 = q1;
00515         else                projPtOnLine_2 = q1 + k*(q2-q1);
00516         Ncontact = projPtOnLine_2 - projPtOnLine_1;
00517         distance = Ncontact.Length();
00518         Ncontact.Normalized();
00519     }
00520     //---------------------------------------------------------------
00521     // Parallel Case
00522     else {
00523         //std::cout << "Parallel Case\n";
00524         T k1;
00525         FindProjectedPointOnALine( p1, q1, q2, k1 );
00526         if ( 0 <= k1 && k1 <= 1 ) {
00527             //std::cout << "( 0 <= k1 && k1 <= 1 )\n";
00528             Vector3<T> q = q1 + k1*(q2-q1);
00529             Ncontact = q - p1;
00530             distance = Ncontact.Length();
00531             Ncontact.Normalized();
00532             return;
00533         }
00534         T k2;
00535         FindProjectedPointOnALine( p2, q1, q2, k2 );
00536         if ( 0 <= k2 && k2 <= 1 ) {
00537             //std::cout << "( 0 <= k2 && k2 <= 1 )\n";
00538             Vector3<T> q = q1 + k2*(q2-q1);
00539             Ncontact = q - p2;
00540             distance = Ncontact.Length();
00541             Ncontact.Normalized();
00542             return;
00543         }
00544         //std::cout << "k1: " << k1 << " k2: " << k2 << "\n";
00545         if ( fabs(k1) < fabs(k2) ) {
00546             //std::cout << "k1 < k2\n";
00547             T dist = (q1 - p1).SquaredLength();
00548             distance = (q1 - p2).SquaredLength();
00549             if ( dist < distance ) {
00550                 //std::cout << "(q1 - p1)\n";
00551                 distance = sqrt( dist );
00552                 Ncontact = (q1 - p1).Normalized();
00553                 return;
00554             }
00555             else {
00556                 //std::cout << "(q1 - p2)\n";
00557                 distance = sqrt( distance );
00558                 Ncontact = (q1 - p2).Normalized();
00559                 return;
00560             }
00561         }
00562         else {
00563             //std::cout << "k2 < k1\n";
00564             T dist = (q2 - p1).SquaredLength();
00565             distance = (q2 - p2).SquaredLength();
00566             if ( dist < distance ) {
00567                 //std::cout << "(q2 - p1)\n";
00568                 distance = sqrt( dist );
00569                 Ncontact = (q2 - p1).Normalized();
00570                 return;
00571             }
00572             else {
00573                 //std::cout << "(q2 - p2)\n";
00574                 distance = sqrt( distance );
00575                 Ncontact = (q2 - p2).Normalized();
00576                 return;
00577             }
00578         }
00579     }
00580     //---------------------------------------------------------------
00581 }
00582 //-----------------------------------------------------------------------------
00583 
00584 
00585 //*****************************************************************************
00586 // Find the projection point to a plane defined its normal and a point on it
00587 // I/P: a point followed by a point on the plane and its normal
00588 // O/P: the projected point on the plane defined by the line, and the distance
00589 //*****************************************************************************
00590 template <typename T>
00591 void CGMath<T>::FindProjectedPointOnAPlane ( 
00592                     Vector3<T> const & p,   // I/P: a point
00593                     Vector3<T> const & a,   // I/P: a point on the plane
00594                     Vector3<T> const & n,   // I/P: the plane normal
00595                     Vector3<T> & q,     // O/P: q = the projected pt of p
00596                     T & distance        // O/P: distance = (p - a)*n
00597 )
00598 {
00599     //---------------------------------------------------------------
00600     // plane constant
00601     //T Kplane = a * n;
00602     //---------------------------------------------------------------
00603     //q = p - ( p*n - Kplane ) * n;
00604     //distance = (q - p).Length();
00605     //distance = (p - a)*n;
00606     distance = (p - a)*n;
00607     q = p - distance*n;
00608     distance = fabs( distance );
00609 }
00610 //-----------------------------------------------------------------------------
00611 //*****************************************************************************
00612 // Find the projection point to a plane defined its normal and a point on it
00613 // I/P: a point followed by a point on the plane and its normal
00614 // O/P: the projected point on the plane defined by the line
00615 //*****************************************************************************
00616 template <typename T>
00617 void CGMath<T>::FindProjectedPointOnAPlane ( 
00618                     Vector3<T> const & p,   // I/P: a point
00619                     Vector3<T> const & a,   // I/P: a point on the plane
00620                     Vector3<T> const & n,   // I/P: the plane normal
00621                     Vector3<T> & q      // O/P: q = the projected pt of p
00622 )
00623 {
00624     q = p - ( (p - a)*n )*n;
00625 }
00626 //-----------------------------------------------------------------------------
00627 //*****************************************************************************
00628 // Find the projection point to a line
00629 // I/P: a point followed by the first and second points defining a line
00630 // O/P: the ratio, the projected point on the line, and the distance
00631 //*****************************************************************************
00632 template <typename T>
00633 void CGMath<T>::FindProjectedPointOnALine ( 
00634                     Vector3<T> const & p,   // I/P: a point
00635                     Vector3<T> const & p1, Vector3<T> const & p2, // I/P: a line
00636                     T & ratio,          // O/P: ratio
00637                     Vector3<T> & q,     // O/P: q = p1 + ratio*(p1-p2)
00638                     T & distance        // O/P: distance = |p - q|
00639 )
00640 {
00641     Vector3<T> p2_p1 = p2 - p1;
00642     ratio = ((p-p1)*p2_p1) / (p2_p1*p2_p1);
00643     q = p1 + ratio*(p2 - p1);
00644     distance = (q - p).Length();
00645 }
00646 //-----------------------------------------------------------------------------
00647 //*****************************************************************************
00648 // Find the projection point to a line
00649 // I/P: a point followed by the first and second points defining a line
00650 // O/P: the ratio and the projected point on the line
00651 //*****************************************************************************
00652 template <typename T>
00653 void CGMath<T>::FindProjectedPointOnALine ( 
00654                     Vector3<T> const & p,   // I/P: a point
00655                     Vector3<T> const & p1, Vector3<T> const & p2, // I/P: a line
00656                     T & ratio,          // O/P: ratio
00657                     Vector3<T> & q      // O/P: q = p1 + ratio*(p1-p2)
00658 )
00659 {
00660     Vector3<T> p2_p1 = p2 - p1;
00661     ratio = ((p-p1)*p2_p1) / (p2_p1*p2_p1);
00662     q = p1 + ratio*(p2 - p1);
00663 }
00664 //-----------------------------------------------------------------------------
00665 //*****************************************************************************
00666 // Find the projection point to a line
00667 // I/P: a point followed by the first and second points defining a line
00668 // O/P: the ratio
00669 //******************************************************************************
00670 template <typename T>
00671 void CGMath<T>::FindProjectedPointOnALine ( 
00672                     Vector3<T> const & p,   // I/P: a point
00673                     Vector3<T> const & p1, Vector3<T> const & p2, // I/P: a line
00674                     T & ratio           // O/P: ratio
00675 )
00676 {
00677     Vector3<T> p2_p1 = p2 - p1;
00678     ratio = ((p-p1)*p2_p1) / (p2_p1*p2_p1);
00679 }
00680 //-----------------------------------------------------------------------------
00681 //*****************************************************************************
00682 // Find LineSegment-LineSegment Intersection
00683 // I/P: two vectors defining the first line segment
00684 // I/P: two vectors defining the second line segment
00685 // O/P: return true then parameter t1 and t2 where 
00686 //        where intersection_pt = p1 + t1(q1-p1) = p2 + t2(q2-p2)
00687 //      return false then parameter t1 and t2 are meaningless
00688 
00689 // PROTENTIAL BUGS
00690 //   Have to check that t1 and t2 return values are valids for all cases
00691 //*****************************************************************************
00692 template <typename T>
00693 bool CGMath<T>::FindIntersectionLineSegmentLineSegment (
00694         Vector3<T> const & p1,      // first line segment
00695         Vector3<T> const & q1, 
00696         Vector3<T> const & p2,      // second line segment
00697         Vector3<T> const & q2, 
00698         T & t1,     // parameter for first line segment
00699                         // where intersection_pt = p1 + t1(q1-p1)
00700         T & t2,     // parameter for second line segment
00701                         // where intersection_pt = p2 + t2(q2-p2)
00702         bool & touching,            // Touching instead of Intersecting
00703         T tolerance
00704 )
00705 {
00706     touching = false;
00707     //--------------------------------------------------------------------
00708     Vector3<T> V1( q1 - p1 );
00709     Vector3<T> V2( q2 - p2 );
00710     Vector3<T> N( V1 ^ V2 );
00711     //--------------------------------------------------------------------
00712     // Line segments are parallel
00713     if ( fabs( N.Length() ) < tolerance ) {
00714         //-----------------------------------------------------------
00715         // Test if q1,p1,q2 are not on the same line
00716         if ( fabs( (V1^( q2 - p1 )).Length() ) >= tolerance )   return false;
00717         //-----------------------------------------------------------
00718         // Transform to x-axis
00719         Matrix3x3<T> rotationMat;
00720         if ( p1.Length() > tolerance ) {
00721             rotationMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
00722                         //p1, Vector3<T>(1,0,0) );
00723                         p1, VectorX );
00724         }
00725         else if ( q1.Length() > tolerance ) {
00726             rotationMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
00727                         //q1, Vector3<T>(1,0,0) );
00728                         q1, VectorX );
00729         }
00730         else if ( p2.Length() > tolerance ) {
00731             rotationMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
00732                         //p2, Vector3<T>(1,0,0) );
00733                         p2, VectorX );
00734         }
00735         else if ( q2.Length() > tolerance ) {
00736             rotationMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
00737                         //q2, Vector3<T>(1,0,0) );
00738                         q2, VectorX );
00739         }
00740         else {
00741             std::cerr << "Line segments are just a point!!!" << std::endl;
00742             assert( false );
00743             return false;
00744         }
00745         //-----------------------------------------------------------
00746         T pp1 = ( rotationMat * p1 )[0];
00747         T pq1 = ( rotationMat * q1 )[0];
00748         T pp2 = ( rotationMat * p2 )[0];
00749         T pq2 = ( rotationMat * q2 )[0];
00750         T A, B, C, D;
00751         if ( pp1 <= pq1 ) {
00752             A = pp1;
00753             B = pq1;
00754         }
00755         else {
00756             A = pq1;
00757             B = pp1;
00758         }
00759         if ( pp2 <= pq2 ) {
00760             C = pp2;
00761             D = pq2;
00762         }
00763         else {
00764             C = pq2;
00765             D = pp2;
00766         }
00767         //-----------------------------------------------------------
00768         //  A-----B  C------D
00769         //  C------D  A-----B
00770         if ( B < C || D < A ) {
00771             return false;
00772         }
00773         else {
00774             // FINISH IT!
00775             // make ratio
00776             return true;
00777         }
00778     }
00779     //--------------------------------------------------------------------
00780     //std::cout << "D1: " << N*p1 << "  D2: " << N*p2 << "\n";
00781     //std::cout << fabs(N*p1 - N*p2) << " < " << tolerance << "\n";
00782     //--------------------------------------------------------------------
00783     /*
00784     glPushMatrix();
00785         //glTranslatef( 0, -2, 0 );
00786         glLineWidth( 5 );
00787         glBegin( GL_LINES );
00788             glColor3f( 1, 0, 0 );
00789             glVertex3fv( &(p1).GetDataFloat() );
00790             glVertex3fv( &(q1).GetDataFloat() );
00791             glVertex3fv( &(p2).GetDataFloat() );
00792             glVertex3fv( &(q2).GetDataFloat() );
00793         glEnd();
00794         glBegin( GL_LINES );
00795             glColor3f( 1, 0, 0 );
00796             glVertex3fv( &(p2).GetDataFloat() );
00797             glVertex3fv( &(p2 + p1-p2).GetDataFloat() );
00798         glEnd();
00799         glLineWidth( 3 );
00800         glBegin( GL_LINES );
00801             glColor3f( 0, 0, 1 );
00802             glVertex3fv( &(p2).GetDataFloat() );
00803             glVertex3fv( &(p2 + V2).GetDataFloat() );
00804         glEnd();
00805         glLineWidth( 1 );
00806     glPopMatrix();
00807     //*/
00808     //--------------------------------------------------------------------
00809     // Check if a point p1 of line segment#1 lies on line segment#2
00810     {
00811         Vector3<T> p1p2( p1 - p2 );
00812         if ( fabs( (p1p2 ^ V2).Length() ) < tolerance ) {
00813             //std::cout << "p1p2\n";
00814             t1 = 0;
00815             T length = V2.Length();
00816             V2.Normalized();
00817             t2 = (p1p2 * V2) / length;
00818             //std::cout << "t1: " << t1 << "\n";
00819             //std::cout << "t2: " << t2 << "\n";
00820             //-------------------------------------------------------
00821             if ( 0 <= t2 && t2 <= 1 ) {
00822                 touching = true;
00823                 return true;
00824             }
00825             else {
00826                 return false;
00827             }
00828         }
00829     }
00830     //--------------------------------------------------------------------
00831     // Check if a point q1 of line segment#1 lies on line segment#2
00832     {
00833         Vector3<T> q1p2( q1 - p2 );
00834         if ( fabs( (q1p2 ^ V2).Length() ) < tolerance ) {
00835             //std::cout << "q1p2\n";
00836             t1 = 1;
00837             T length = V2.Length();
00838             V2.Normalized();
00839             t2 = (q1p2 * V2) / length;
00840             //std::cout << "t1: " << t1 << "\n";
00841             //std::cout << "t2: " << t2 << "\n";
00842             //-------------------------------------------------------
00843             if ( 0 <= t2 && t2 <= 1 ) {
00844                 touching = true;
00845                 return true;
00846             }
00847             else {
00848                 return false;
00849             }
00850         }
00851     }
00852     //--------------------------------------------------------------------
00853     // Check if a point p2 of line segment#2 lies on line segment#1
00854     {
00855         Vector3<T> p2p1( p2 - p1 );
00856         if ( fabs( (p2p1 ^ V1).Length() ) < tolerance ) {
00857             //std::cout << "p2p1\n";
00858             t2 = 0;
00859             T length = V1.Length();
00860             V1.Normalized();
00861             t1 = (p2p1 * V1) / length;
00862             //std::cout << "t1: " << t1 << "\n";
00863             //std::cout << "t2: " << t2 << "\n";
00864             //-------------------------------------------------------
00865             if ( 0 <= t1 && t1 <= 1 ) {
00866                 touching = true;
00867                 return true;
00868             }
00869             else {
00870                 return false;
00871             }
00872         }
00873     }
00874     //--------------------------------------------------------------------
00875     // Check if a point q2 of line segment#2 lies on line segment#1
00876     {
00877         Vector3<T> q2p1( q2 - p1 );
00878         if ( fabs( (q2p1 ^ V1).Length() ) < tolerance ) {
00879             //std::cout << "q2p1\n";
00880             t2 = 1;
00881             T length = V1.Length();
00882             V1.Normalized();
00883             t1 = (q2p1 * V1) / length;
00884             //std::cout << "t1: " << t1 << "\n";
00885             //std::cout << "t2: " << t2 << "\n";
00886             //-------------------------------------------------------
00887             if ( 0 <= t1 && t1 <= 1 ) {
00888                 touching = true;
00889                 return true;
00890             }
00891             else {
00892                 return false;
00893             }
00894         }
00895     }
00896     //--------------------------------------------------------------------
00897     // Check if the line segments are on the same plane level
00898     N = (V1 ^ ( q2 - p1 )).Normalized();    // Get normal from q1p1 ^ q2p1
00899 
00900     //Vector3<T> N1 = (V1 ^ ( q2 - p1 )).Normalized();
00901     //Vector3<T> N2 = (V1 ^ ( p2 - p1 )).Normalized();
00902     //if ( fabs( (N1-N2).Length() ) > tolerance ) {
00903     //  std::cout << "Line Segments are NOT on the same plane!\n";
00904     //}
00905     //else {
00906     //  std::cout << "Line Segments are on the same plane!\n";
00907     //}
00908 
00909     //--------------------------------------------------------------------
00910     //std::cout << "N*p1: " << N*p1 << "\n";
00911     //std::cout << "N*p2: " << N*p2 << "\n";
00912     //--------------------------------------------------------------------
00913     if ( fabs(N*p1 - N*p2) > tolerance ) {
00914         //std::cout << "Line Segments are NOT on the same plane!\n";
00915         return false;
00916     }
00917     else {
00918         //std::cout << "Line Segments are on the same plane!\n";
00919     }
00920     //--------------------------------------------------------------------
00921     Vector3<T> K1 = N ^ V1;
00922     Vector3<T> K2 = N ^ V2;
00923     t1 = ( K2 * ( p2 - p1 ) ) / ( K2 * V1 );
00924     t2 = ( K1 * ( p1 - p2 ) ) / ( K1 * V2 );
00925     //--------------------------------------------------------------------
00926     //std::cout << "t1: " << t1 << "\n";
00927     //std::cout << "t2: " << t2 << "\n";
00928     //--------------------------------------------------------------------
00929     if ( 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1 ) {
00930         if ( t1 == 0 || t1 == 1 || t2 == 0 || t2 == 1 ) {
00931             touching = true;
00932         }
00933         return true;
00934     }
00935     else    return false;
00936     //--------------------------------------------------------------------
00937     return false;
00938 }
00939 //-----------------------------------------------------------------------------
00940 
00941 
00942 //*****************************************************************************
00943 // Find Circle-Triangle Intersection
00944 // I/P: a vector defining the circle center, a scalar value defining the sphere radius, 
00945 // and a vector defining the circle normal (defining circle plane)
00946 // I/P: three vectors defining the triangle in counter-clockwise dir
00947 // O/P: three vectors for moving the triangle's points to resolve the intersection
00948 //*****************************************************************************
00949 template <typename T>
00950 bool CGMath<T>::FindIntersectionCircleTriangle (
00951         // I/P:
00952         Vector3<T> const & center,  
00953         T                  radius,  
00954         Vector3<T> const & normal,  
00955         Vector3<T> const & p,       
00956         Vector3<T> const & q,       
00957         Vector3<T> const & r,       
00958         // O/P:
00959         Vector3<T> & outVec_1,      
00960         Vector3<T> & outVec_2,      
00961         Vector3<T> & outVec_3,      
00962         // O/P: (for translating to force feedback)
00963         Vector3<T> * contactPt,     
00964         // Threshold for zero value
00965         T tolerance = Math<T>::ThresholdZero    
00966 )
00967 {
00968     return false;
00969 }
00970 //-----------------------------------------------------------------------------
00971 
00972 
00973 //*****************************************************************************
00974 // Find Sphere-Triangle Intersection
00975 // I/P: one vector defining the sphere center and a scalar value defining the sphere radius
00976 // I/P: three vectors defining the triangle in counter-clockwise dir
00977 //*****************************************************************************
00978 template <typename T>
00979 bool CGMath<T>::FindIntersectionSphereTriangle (
00980         // I/P:
00981         Vector3<T> const & center,  
00982         T                  radius,  
00983         Vector3<T> const & p,       
00984         Vector3<T> const & q,       
00985         Vector3<T> const & r,       
00986         T tolerance = Math<T>::ThresholdZero    
00987 )
00988 {
00989     //---------------------------------------------------------------
00990     // Simplify the computation by 
00991     // transforming the sphere to the origin
00992     //      _______
00993     //     /   |   \
00994     //     |(0,0,0)| 
00995     //     \___|___/
00996     //
00997     // I.e., the triangle must be translated by the negative of sphere center.
00998     Vector3<T> pp( p - center );
00999     Vector3<T> qq( q - center );
01000     Vector3<T> rr( r - center );
01001     //---------------------------------------------------------------
01002     //***************************************************************
01003     //---------------------------------------------------------------
01004     // Let P1 is the plane containing the triangle
01005     //
01006     //---------------------------------------------------------------
01007     // Case 1:  Sphere does not intersect with the triangle if sphere's 
01008     //          closest point to P1 is more than its radius away from P1
01009     //---------------------------------------------------------------
01010     // Case 2:  sphere's closest point to P1 is NOT more than its radius 
01011     //          away from P1
01012     //   Sphere may intersects with the triangle
01013     //---------------------------------------------------------------
01014     //***************************************************************
01015     //---------------------------------------------------------------
01016     // Find the normal of the triangle
01017     Vector3<T> N = (qq - pp) ^ (rr - pp);
01018     N.Normalized();
01019     //---------------------------------------------------------------
01020     // Plane constant tells how far the plane is from the origin.
01021     T P1 = pp * N;      // Plane Constant
01022     //---------------------------------------------------------------
01023     //***************************************************************
01024     // CASE 1: Sphere center (at origin) is more than its radius away from P1
01025     //---------------------------------------------------------------
01026     if ( fabs( P1 ) > radius )  return false;
01027     //---------------------------------------------------------------
01028     //***************************************************************
01029     // CASE 2: Sphere center (at origin) is NOT more than its radius away from P1
01030     //---------------------------------------------------------------
01031     // Create a circle centering on the triangle plane from the sphere
01032     // The circle center is the closest point from the sphere to the triangle plane
01033     // The circle radius is the radius of circle created by the sphere intersecting the triangle plane
01034     T           distance;       // the distance of the closest pt to the plane
01035     Vector3<T>  circleCenter;   // the projected point on the plane
01036     FindProjectedPointOnAPlane( ZeroVector, pp, N, circleCenter, distance );
01037     T circleRadius = sqrt( radius*radius - distance*distance );
01038 
01039     if ( FindIfACircleIntersectsATriangleOnTheSamePlane( circleCenter, circleRadius, pp, qq, rr, tolerance ) > 0 ) {
01040         return true;
01041     }
01042     else {
01043         return false;
01044     }
01045 }
01046 //-----------------------------------------------------------------------------
01047 
01048 
01049 //*****************************************************************************
01050 // Find Sphere-Triangle Intersection
01051 // I/P: one vector defining the sphere center and a scalar value defining the sphere radius
01052 // I/P: three vectors defining the triangle in counter-clockwise dir
01053 // O/P: three vectors for moving the triangle's points to resolve the intersection
01054 //*****************************************************************************
01055 template <typename T>
01056 bool CGMath<T>::FindIntersectionSphereTriangle (
01057         // I/P:
01058         Vector3<T> const & center,  
01059         T                  radius,  
01060         Vector3<T> const & p,       
01061         Vector3<T> const & q,       
01062         Vector3<T> const & r,       
01063         // O/P:
01064         Vector3<T> & outVec_1,      
01065         Vector3<T> & outVec_2,      
01066         Vector3<T> & outVec_3,      
01067         // O/P: (for translating to force feedback)
01068         Vector3<T> * contactPt,     
01069         // Threshold for zero value
01070         T tolerance = Math<T>::ThresholdZero    
01071 )
01072 {
01073     //---------------------------------------------------------------
01074     // Simplify the computation by 
01075     // transforming the sphere to the origin
01076     //      _______
01077     //     /   |   \
01078     //     |(0,0,0)| 
01079     //     \___|___/
01080     //
01081     // I.e., the triangle must be translated by the negative of sphere center.
01082     Vector3<T> pp( p - center );
01083     Vector3<T> qq( q - center );
01084     Vector3<T> rr( r - center );
01085     //---------------------------------------------------------------
01086     //***************************************************************
01087     //---------------------------------------------------------------
01088     // Let P1 is the plane containing the triangle
01089     //
01090     //---------------------------------------------------------------
01091     // Case 1:  Sphere does not intersect with the triangle if sphere's 
01092     //          closest point to P1 is more than its radius away from P1
01093     //---------------------------------------------------------------
01094     // Case 2:  sphere's closest point to P1 is NOT more than its radius 
01095     //          away from P1
01096     //   Sphere may intersects with the triangle
01097     //---------------------------------------------------------------
01098     //***************************************************************
01099     //---------------------------------------------------------------
01100     // Find the normal of the triangle
01101     Vector3<T> N = (qq - pp) ^ (rr - pp);
01102     N.Normalized();
01103     //---------------------------------------------------------------
01104     // Plane constant tells how far the plane is from the origin.
01105     T P1 = pp * N;      // Plane Constant
01106     //---------------------------------------------------------------
01107     //***************************************************************
01108     // CASE 1: Sphere center (at origin) is more than its radius away from P1
01109     //---------------------------------------------------------------
01110     if ( fabs( P1 ) > radius ) {
01111         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01112         return false;
01113     }
01114     //---------------------------------------------------------------
01115     //***************************************************************
01116     // CASE 2: Sphere center (at origin) is NOT more than its radius away from P1
01117     //---------------------------------------------------------------
01118     // Create a circle centering on the triangle plane from the sphere
01119     // The circle center is the closest point from the sphere to the triangle plane
01120     // The circle radius is the radius of circle created by the sphere intersecting the triangle plane
01121     //      _______
01122     //     /   |   \
01123     //     |(0,0,0)| 
01124     //     \___|___/
01125     //         |
01126     //         |
01127     //       ------
01128     //       \ *  /   (*) is the projected point from the origin to the triangle
01129     //        \  /
01130     //         \/
01131     //
01132     T           distance;       // the distance of the closest pt to the plane
01133     Vector3<T>  circleCenter;   // the projected point on the plane
01134     FindProjectedPointOnAPlane( ZeroVector, pp, N, circleCenter, distance );
01135     T circleRadius = sqrt( radius*radius - distance*distance );
01136 
01137     // Test if the projected point (circleCenter) lies inside the triangle
01138     if ( FindIfAPointIsInATriangleOnTheSamePlane( circleCenter, pp, qq, rr, tolerance ) )
01139     {
01140         // All output vectors are set to the same value.
01141         Vector3<T> pt( ( circleCenter + CentroidOfTriangle(pp,qq,rr) ).Normalized() );
01142         outVec_1 = outVec_2 = outVec_3 = pt * (radius - distance);
01143         if ( contactPt ) {
01144             *contactPt = pt * radius + center;
01145         }
01146 
01147         // Old way
01148         // All output vectors are set to the same value.
01149         //outVec_1 = outVec_2 = outVec_3 = circleCenter.Normalized() * (radius - distance);
01150         //if ( contactPt ) {
01151         //  *contactPt = circleCenter * radius;
01152         //}
01153         return true;
01154     }
01155 
01156     // Test if the projected circle intersects the triangle, while its center (circleCenter) is outside the triangle
01157     int result = FindIfACircleIntersectsATriangleOnTheSamePlane( circleCenter, circleRadius, pp, qq, rr, tolerance );
01158 
01159     // DEBUG
01160     // For the collision case from FindIfACircleIntersectsATriangleOnTheSamePlane Fn
01161     //std::cout << "Result: " << result << "\n";
01162 
01163     switch ( result ) {
01164         case 0:
01165             if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01166             return false;
01167             break;
01168         case 1:     // See FindIfACircleIntersectsATriangleOnTheSamePlane Fn for detail
01169             {
01170                 Vector3<T> pt( ( circleCenter + CentroidOfTriangle(pp,qq,rr) ).Normalized() );
01171                 outVec_1 = outVec_2 = pt * (radius - distance);
01172                 outVec_3.SetXYZ( 0, 0, 0 );
01173                 if ( contactPt ) {
01174                     *contactPt =  pt * radius + center;
01175                 }
01176             }
01177             break;
01178         case 2:     // See FindIfACircleIntersectsATriangleOnTheSamePlane Fn for detail
01179             {
01180                 Vector3<T> pt( ( circleCenter + CentroidOfTriangle(pp,qq,rr) ).Normalized() );
01181                 outVec_2 = outVec_3 = pt * (radius - distance);
01182                 outVec_1.SetXYZ( 0, 0, 0 );
01183                 if ( contactPt ) {
01184                     *contactPt =  pt * radius + center;
01185                 }
01186             }
01187             break;
01188         case 3:     // See FindIfACircleIntersectsATriangleOnTheSamePlane Fn for detail
01189             {
01190                 Vector3<T> pt( ( circleCenter + CentroidOfTriangle(pp,qq,rr) ).Normalized() );
01191                 outVec_1 = outVec_3 = pt * (radius - distance);
01192                 outVec_2.SetXYZ( 0, 0, 0 );
01193                 if ( contactPt ) {
01194                     *contactPt =  pt * radius + center;
01195                 }
01196             }
01197             break;
01198         case 11:    // See FindIfACircleIntersectsATriangleOnTheSamePlane Fn for detail
01199         case 21:    // See FindIfACircleIntersectsATriangleOnTheSamePlane Fn for detail
01200             // Already covered by the test above
01201             //   "Test if the projected point (circleCenter) lies inside the triangle"
01202             if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01203             return false;
01204             break;
01205     }
01206 
01207     return true;
01208 }
01209 //-----------------------------------------------------------------------------
01210 
01211 
01212 
01213 
01214 //*****************************************************************************
01215 // Find Cylinder-Cylinder Intersection
01216 // I/P: four vectors defining two lines with two radii to define two cylinders
01217 // O/P: a closest distance vector
01218 //*****************************************************************************
01219 template <typename T>
01220 bool CGMath<T>::FindIntersectionCylinderCylinder (
01221     // I/P:
01222     Vector3<T> const & cA1,         // first  point of the 1st cylinder
01223     Vector3<T> const & cA2,         // second point of the 1st cylinder
01224     T                  cAradius,    // radius of the 1st cylinder
01225     Vector3<T> const & cB1,         // first  point of the 2nd cylinder
01226     Vector3<T> const & cB2,         // second point of the 2nd cylinder
01227     T                  cBradius,    // radius of the 2nd cylinder
01228     // O/P:
01229     Vector3<T> & distVector,        // the closest distance vector of the two cylinders
01230     // Threshold for zero value
01231     T tolerance = Math<T>::ThresholdZero    // thereshold for zero value 
01232 )
01233 {
01234     //---------------------------------------------------------------
01235     T k;
01236     Vector3<T> pq1, pq2, pq3;
01237     //---------------------------------------------------------------
01238     // Find the projected point (pq1) of cA1 on the line defined by cB2-cB1
01239     FindProjectedPointOnALine( cA1, cB1, cB2, k, pq1 );
01240     //---------------------------------------------------------------
01241     // Find the projected point (pq2) of cA2 on the line defined by cB2-cB1
01242     FindProjectedPointOnALine( cA2, cB1, cB2, k, pq2 );
01243     //---------------------------------------------------------------
01244     // Find the projected point (pq3) of p2 on the plane defined by the 
01245     //   point pq1 and the plane normal defined by (cB2-cB1)
01246     FindProjectedPointOnAPlane( cA2, cA1, (cB2-cB1).Normalized(), pq3 );
01247     //---------------------------------------------------------------
01248     T d3 = (cA1 - pq3).SquaredLength();
01249     //---------------------------------------------------------------
01250     if ( d3 > cAradius + cBradius ) return false;   // Not intersect
01251     //---------------------------------------------------------------
01252     // Unparallel Case
01253     if ( d3 > tolerance ) {
01254         Vector3<T> ps;
01255         Vector3<T> qs;
01256         T d1 = (cA1 - pq1).SquaredLength();
01257         T d2 = (cA2 - pq2).SquaredLength();
01258         k = ( d1 - d2 + d3 ) / d3 / static_cast<T>( 2.0 );
01259         if      ( k >= 1 )  ps = cA2;
01260         else if ( k <= 0 )  ps = cA1;
01261         else                ps = cA1 + k*(cA2-cA1);
01262         FindProjectedPointOnALine( ps, cB1, cB2, k );
01263         if      ( k >= 1 )  qs = cB2;
01264         else if ( k <= 0 )  qs = cB1;
01265         else                qs = cB1 + k*(cB2-cB1);
01266         distVector = qs - ps;
01267         return true;
01268     }
01269     //---------------------------------------------------------------
01270     // Parallel Case
01271     else {
01272         T k1;
01273         FindProjectedPointOnALine( cA1, cB1, cB2, k1 );
01274         if ( 0 <= k1 && k1 <= 1 ) {
01275             Vector3<T> q = cB1 + k1*(cB2-cB1);
01276             distVector = q - cA1;
01277             return true;
01278         }
01279         T k2;
01280         FindProjectedPointOnALine( cA2, cB1, cB2, k2 );
01281         if ( 0 <= k2 && k2 <= 1 ) {
01282             Vector3<T> q = cB1 + k2*(cB2-cB1);
01283             distVector = q - cA2;
01284             return true;
01285         }
01286         if ( fabs(k1) < fabs(k2) ) {
01287             T dist = (cB1 - cA1).SquaredLength();
01288             T distance = (cB1 - cA2).SquaredLength();
01289             if ( dist < distance ) {
01290                 distVector = cB1 - cA1;
01291                 return true;
01292             }
01293             else {
01294                 distVector = cB1 - cA2;
01295                 return true;
01296             }
01297         }
01298         else {
01299             T dist = (cB2 - cA1).SquaredLength();
01300             T distance = (cB2 - cA2).SquaredLength();
01301             if ( dist < distance ) {
01302                 distVector = cB2 - cA1;
01303                 return true;
01304             }
01305             else {
01306                 distVector = cB2 - cA2;
01307                 return true;
01308             }
01309         }
01310     }
01311     //---------------------------------------------------------------
01312 }
01313 
01314 
01315 
01316 
01317 //*****************************************************************************
01318 // Find Cylinder-Triangle Intersection
01319 // I/P: two vectors defining a line and a radius defining a cylinder
01320 // I/P: three vectors defining second triangle in counter-clockwise dir
01321 // O/P: a closest distance (not implemented yet)
01322 //*****************************************************************************
01323 template <typename T>
01324 bool CGMath<T>::FindIntersectionCylinderTriangle (
01325         // I:P:
01326         Vector3<T> const & c1,      // first  point of cylinder
01327         Vector3<T> const & c2,      // second point of cylinder
01328         T                  radius,  // radius of cylinder
01329         Vector3<T> const & p,       // triangle
01330         Vector3<T> const & q, 
01331         Vector3<T> const & r, 
01332         // Threshold for zero value
01333         T tolerance = Math<T>::ThresholdZero    
01334 )
01335 {
01336     //--------------------------------------------------------------------
01337     // Transform the cylinder to align with y-axis with c1 at the origin
01338     //
01339     //      __l2__
01340     //         |
01341     //      (0,0,0)
01342     //      ___|__
01343     //        l1
01344     //
01345     Vector3<T> l2( (c2-c1)/2 );
01346     T tCylinderHalfLength = l2.Length();
01347     Vector3<T> vTranslator( l2 + c1 );
01348     Matrix3x3<T> rotMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
01349                             l2, VectorY );
01350     l2.SetXYZ(     0,  tCylinderHalfLength, 0 );
01351     Vector3<T> l1( 0, -tCylinderHalfLength, 0 );
01352     //Vector3<T> l1 = rotMat * ( c1 - vTranslator );
01353     //l2 = rotMat * ( c2 - vTranslator );
01354     //--------------------------------------------------------------------
01355     // Transform the triangle with the same transformation for cylinder
01356     Vector3<T> pp( rotMat * ( p - vTranslator ) );
01357     Vector3<T> qq( rotMat * ( q - vTranslator ) );
01358     Vector3<T> rr( rotMat * ( r - vTranslator ) );
01359     //--------------------------------------------------------------------
01360     //--------------------------------------------------------------------
01361     //********************************************************************
01362     //--------------------------------------------------------------------
01363     // Let P1 is the plane containing the triangle
01364     //
01365     //--------------------------------------------------------------------
01366     // Case 1:  Cylinder does not intersect with the triangle 
01367     //          if both vertices of cylinder lie above or below P1
01368     //--------------------------------------------------------------------
01369     // Case 2:  Each vertex of cylinder lies on opposite side of P1
01370     //   Cylinder may intersects with the triangle
01371     //--------------------------------------------------------------------
01372     // Case 3:  One vertex of cylinder lies on one side of P1
01373     //          and the other lies on P1
01374     //   Cylinder may intersects with the triangle
01375     //--------------------------------------------------------------------
01376     // Case 4:  The cylinder is parallel with the plane of the triangle
01377     //          e.g. both c1 and c2 lies on the plane of the triangle
01378     //   Cylinder may intersects with the triangle
01379     //--------------------------------------------------------------------
01380     //********************************************************************
01381     // CASE 1: Both vertices of cylinder lie above or below P1
01382     //--------------------------------------------------------------------
01383     // Reject if all triangle point lies below y-value of l1
01384     T lowValue = -tolerance + l1[1];
01385     if ( pp[1] < lowValue && qq[1] < lowValue && rr[1] < lowValue ) {
01386     //if ( pp[1] < 0 && qq[1] < 0 && rr[1] < 0 ) {
01387         //std::cout << "Reject if all triangle point lies below y=0 (y of c1)\n";
01388         TAPsDebugMessage( "Reject if all triangle point lies below local y of c1\n" );
01389         return false;
01390     }
01391     //--------------------------------------------------------------------
01392     // Reject if all triangle point lies above y-value of l2
01393     T highValue = tolerance + l2[1];
01394     if ( pp[1] > highValue && qq[1] > highValue && rr[1] > highValue ) {
01395         //std::cout << "Reject if all triangle point lies above y of l2\n";
01396         TAPsDebugMessage( "Reject if all triangle point lies above local y of c2\n" );
01397         return false;
01398     }
01399     //--------------------------------------------------------------------
01400     //********************************************************************
01401     //--------------------------------------------------------------------
01402     // Find the normal of the triangle
01403     Vector3<T> N = (qq - pp) ^ (rr - pp);
01404     N.Normalized();
01405     //--------------------------------------------------------------------
01406     // Find where vertices of cylinder lie on which side of P1 plane
01407     T Kplane = pp * N;      // Plane Constant
01408     T l1P = N*l1 - Kplane;
01409     T l2P = N*l2 - Kplane;
01410     T zero = Math<T>::ZERO;
01411     //--------------------------------------------------------------------
01412     //********************************************************************
01413     // Case 3: c1 lies on the plane, but c2 does not
01414     //--------------------------------------------------------------------
01415     if ( fabs( l1P ) <= tolerance && fabs( l2P ) > tolerance ) {
01416         //l1P = zero;
01417         //-----------------------------------------------------------
01418         // Case the point is in the triangle
01419         bool result = FindIfAPointIsInATriangleOnTheSamePlane( l1, pp, qq, rr, tolerance );
01420         if ( result ) {
01421             //std::cout << "Case the point L1 is in the triangle\n";
01422             TAPsDebugMessage( "Case the point L1 is in the triangle\n" );
01423             return true;
01424         }
01425         //-----------------------------------------------------------
01426         // Case the point is not in the triangle
01427         radius += tolerance;
01428         T ratio, distance;
01429         Vector3<T> projectedPt;
01430         FindProjectedPointOnALine( l1, pp, qq, ratio, projectedPt, distance );
01431         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01432             //std::cout << "Case1 the point L1 is not in the triangle\n";
01433             TAPsDebugMessage( "Case1 the point L1 is not in the triangle\n" );
01434             return true;
01435         }
01436         FindProjectedPointOnALine( l1, qq, rr, ratio, projectedPt, distance );
01437         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01438             //std::cout << "Case2 the point L1 is not in the triangle\n";
01439             TAPsDebugMessage( "Case2 the point L1 is not in the triangle\n" );
01440             return true;
01441         }
01442         FindProjectedPointOnALine( l1, rr, pp, ratio, projectedPt, distance );
01443         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01444             //std::cout << "Case3 the point L1 is not in the triangle\n";
01445             TAPsDebugMessage( "Case3 the point L1 is not in the triangle\n" );
01446             return true;
01447         }
01448         //-----------------------------------------------------------
01449         return false;
01450     }
01451     //--------------------------------------------------------------------
01452     //********************************************************************
01453     // Case 3: c2 lies on the plane, but c1 does not
01454     //--------------------------------------------------------------------
01455     if ( fabs( l2P ) <= tolerance && fabs( l1P ) > tolerance ) {
01456         //l2P = zero;
01457         //-----------------------------------------------------------
01458         // Case the point is in the triangle
01459         bool result = FindIfAPointIsInATriangleOnTheSamePlane( l2, pp, qq, rr, tolerance );
01460         if ( result ) {
01461             //std::cout << "Case the point L2 is in the triangle\n";
01462             TAPsDebugMessage( "Case the point L2 is in the triangle\n" );
01463             return true;
01464         }
01465         //-----------------------------------------------------------
01466         // Case the point is not in the triangle
01467         radius += tolerance;
01468         T ratio, distance;
01469         Vector3<T> projectedPt;
01470         FindProjectedPointOnALine( l2, pp, qq, ratio, projectedPt, distance );
01471         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01472             //std::cout << "Case1 the point L2 is not in the triangle\n";
01473             TAPsDebugMessage( "Case1 the point L2 is not in the triangle\n" );
01474             return true;
01475         }
01476         FindProjectedPointOnALine( l2, qq, rr, ratio, projectedPt, distance );
01477         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01478             //std::cout << "Case2 the point L2 is not in the triangle\n";
01479             TAPsDebugMessage( "Case2 the point L2 is not in the triangle\n" );
01480             return true;
01481         }
01482         FindProjectedPointOnALine( l2, rr, pp, ratio, projectedPt, distance );
01483         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01484             //std::cout << "Case3 the point L2 is not in the triangle\n";
01485             TAPsDebugMessage( "Case3 the point L2 is not in the triangle\n" );
01486             return true;
01487         }
01488         //-----------------------------------------------------------
01489         return false;
01490     }
01491     //--------------------------------------------------------------------
01492     //********************************************************************
01493     // Case 4: The cylinder is parallel with the plane of triangle
01494     //   e.g. both c1 and c2 lies on the plane of the triangle
01495     //--------------------------------------------------------------------
01496     if ( fabs(l1P - l2P) <= tolerance ) {
01497         T distance;
01498         radius += tolerance;
01499         //-----------------------------------------------------------
01500         // Check l1 distance from plane
01501         Vector3<T> projectedPt1;
01502         FindProjectedPointOnAPlane( l1, pp, N, projectedPt1, distance );
01503         //-----------------------------------------------------------
01504         if ( distance > radius )    return false;
01505         //-----------------------------------------------------------
01506         // Case the projected point is in the triangle
01507         {
01508             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01509                                 projectedPt1, pp, qq, rr, tolerance );
01510             if ( result ) {
01511                 //std::cout << "Case Parallel: the projected point L1 is in the triangle\n";
01512                 TAPsDebugMessage( "Case Parallel: the projected point L1 is in the triangle\n" );
01513                 return true;
01514             }
01515         }
01516         //-----------------------------------------------------------
01517         // Check l2 distance from plane
01518         Vector3<T> projectedPt2;
01519         FindProjectedPointOnAPlane( l2, pp, N, projectedPt2, distance );
01520         //-----------------------------------------------------------
01521         if ( distance > radius )    return false;
01522         //-----------------------------------------------------------
01523         // Case the projected point is in the triangle
01524         {
01525             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01526                                 projectedPt2, pp, qq, rr, tolerance );
01527             if ( result ) {
01528                 //std::cout << "Case Parallel: the projected point L2 is in the triangle\n";
01529                 TAPsDebugMessage( "Case Parallel: the projected point L2 is in the triangle\n" );
01530                 return true;
01531             }
01532         }
01533         //-----------------------------------------------------------
01534         // Check if line segment l2-l1 intersects the triangle
01535         T ratio1, ratio2;
01536         bool touching;
01537         if ( FindIntersectionLineSegmentLineSegment( 
01538                 projectedPt1, projectedPt2, pp, qq, ratio1, ratio2, touching, tolerance )
01539         ) {
01540             //std::cout << "Case Parallel: line segment L2-L1 intersects the triangle p-q\n";
01541             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle p-q\n" );
01542             return true;
01543         }
01544         if ( FindIntersectionLineSegmentLineSegment( 
01545                 projectedPt1, projectedPt2, qq, rr, ratio1, ratio2, touching, tolerance )
01546         ) {
01547             //std::cout << "Case Parallel: line segment L2-L1 intersects the triangle q-r\n";
01548             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle q-r\n" );
01549             return true;
01550         }
01551         if ( FindIntersectionLineSegmentLineSegment( 
01552                 projectedPt1, projectedPt2, rr, pp, ratio1, ratio2, touching, tolerance )
01553         ) {
01554             //std::cout << "Case Parallel: line segment L2-L1 intersects the triangle r-p\n";
01555             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle r-p\n" );
01556             return true;
01557         }
01558         //-----------------------------------------------------------
01559         //std::cout << "Case Parallel: line segment L2-L1 DOESN't intersect the triangle\n";
01560         TAPsDebugMessage( "Case Parallel: line segment L2-L1 DOESN't intersect the triangle\n" );
01561         return false;
01562     }
01563     //--------------------------------------------------------------------
01564     // Case the cylinder is not parallel with the plane of triangle
01565     // and either l1 and l2 of cylinder does not lie on the plane of the triangle
01566     radius += tolerance;
01567     //---------------------------------------------------------------
01568 //  if ( ( l1P > radius && l2P > radius ) || ( l1P < -radius && l2P < -radius ) ) {
01569         //TAPsDebugMessage( "Radius (" << radius << "): " << l1P << " " << l2P << "\n" );
01570         //TAPsDebugMessage( "Case Not Parallel1: cylinder skeleton does not intersect the triangle plane\n" );
01571 //      return false;
01572 //  }
01573     /*
01574     //---------------------------------------------------------------
01575     if (   ( l1P > tolerance && l2P > tolerance ) 
01576         || ( l1P < -tolerance && l2P < -tolerance ) ) {
01577         bool finalResult = false;
01578         //------------------------------------------------------
01579         // Project l1 to the triangle plane
01580         {
01581             Vector3<T> projectedPt1( pp - l1P*N );
01582             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01583                                 projectedPt1, pp, qq, rr, tolerance );
01584             //---------------------------------------------
01585             // Case the projected point is in the triangle
01586             if ( result ) {
01587                 //std::cout << "Case Not Parallel (--/++): the projected point of l1 is in the triangle\n";
01588                 TAPsDebugMessage( "Case Not Parallel (--/++): the projected point of l1 is in the triangle\n" );
01589                 //return true;
01590                 finalResult = true;
01591             }
01592         }
01593         //------------------------------------------------------
01594         // Project l2 to the triangle plane
01595         {
01596             Vector3<T> projectedPt2( pp - l2P*N );
01597             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01598                                 projectedPt2, pp, qq, rr, tolerance );
01599             //---------------------------------------------
01600             // Case the projected point is in the triangle
01601             if ( result ) {
01602                 //std::cout << "Case Not Parallel (--/++): the projected point of l2 is in the triangle\n";
01603                 TAPsDebugMessage( "Case Not Parallel (--/++): the projected point of l2 is in the triangle\n" );
01604                 //return true;
01605                 finalResult = true;
01606             }
01607         }
01608 //      return finalResult;
01609     }
01610     //*/
01611     //--------------------------------------------------------------------
01612     //********************************************************************
01613     // CASE 2: Both vertices of cylinder lie above or below P1
01614     //--------------------------------------------------------------------
01615     if ( ( l1P < -tolerance && l2P >  tolerance ) 
01616       || ( l1P >  tolerance && l2P < -tolerance ) ) {
01617         //------------------------------------------------------
01618         // Find the point on the line that intersects the triangle plane
01619         Vector3<T> l2l1( l2-l1 );
01620         T ratio = (N*(pp-l1)) / (N*l2l1);
01621         Vector3<T> projectedPt( l1 + ratio*l2l1 );
01622         //------------------------------------------------------
01623         bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01624                             projectedPt, pp, qq, rr, tolerance );
01625         //------------------------------------------------------
01626         // Case the projected point is in the triangle
01627         if ( result ) {
01628             //std::cout << "Case Not Parallel: the triangle intersects the cylinder axis\n";
01629             TAPsDebugMessage( "Case Not Parallel: the triangle intersects the cylinder axis\n" );
01630             return true;
01631         }
01632     }
01633     //====================================================================
01634     // Final Test
01635     //---------------------------------------------------------------
01636     // Case the projected point is NOT in the triangle
01637     T distance1, distance2, distance3;
01638     Vector3<T> contactNormal1, contactNormal2, contactNormal3;
01639     FindClosestDistanceBetweenTwoLineSegments( 
01640                 l1, l2,         // I/P: a line 
01641                 pp, qq,         // I/P: the pq edge of the triangle
01642                 distance1,      // O/P: distance
01643                 contactNormal1, // O/P: contact normal
01644                 tolerance );
01645     FindClosestDistanceBetweenTwoLineSegments( 
01646                 l1, l2,         // I/P: a line 
01647                 qq, rr,         // I/P: the pq edge of the triangle
01648                 distance2,      // O/P: distance
01649                 contactNormal2, // O/P: contact normal
01650                 tolerance );
01651     FindClosestDistanceBetweenTwoLineSegments( 
01652                 l1, l2,         // I/P: a line 
01653                 rr, pp,         // I/P: the pq edge of the triangle
01654                 distance3,      // O/P: distance
01655                 contactNormal3, // O/P: contact normal
01656                 tolerance );
01657     if ( distance1 < radius || distance2 < radius || distance3 < radius ) {
01658         //std::cout << distance1 << " " << distance2 << " " << distance3 << "\n";
01659         //TAPsDebugMessage ( (distance1) + " " 
01660         //           + (distance2) + " " 
01661         //           + (distance3) + "\n" );
01662         //std::cout << "Case Not Parallel: the projected point is Not in the triangle\n"; 
01663         TAPsDebugMessage( "Case Not Parallel: the projected point is NOT in the triangle, however the cylinder intersects the triangle\n" ); 
01664         return true;
01665     }
01666     //--------------------------------------------------------------------
01667     //====================================================================
01668     //--------------------------------------------------------------------
01669     TAPsDebugMessage( "Reach End of Test for FindIntersectionCylinderTriangle\n" );
01670     return false;
01671 }
01672 // END: FindIntersectionCylinderTriangle W/O Outputs
01673 //-----------------------------------------------------------------------------
01674 
01675 
01676 
01677 
01678 //*****************************************************************************
01679 // Find Cylinder-Triangle Intersection
01680 // I/P: two vectors defining a line and a radius defining a cylinder
01681 // I/P: three vectors defining second triangle in counter-clockwise dir
01682 // O/P: a closest distance (not implemented yet)
01683 //*****************************************************************************
01684 template <typename T>
01685 bool CGMath<T>::FindIntersectionCylinderTriangle (
01686         // I:P:
01687         Vector3<T> const & c1,      // first  point of cylinder
01688         Vector3<T> const & c2,      // second point of cylinder
01689         T                  radius,  // radius of cylinder
01690         Vector3<T> const & p,       // triangle
01691         Vector3<T> const & q, 
01692         Vector3<T> const & r, 
01693         // O/P:
01694         Vector3<T> & outVec_1,      
01695         Vector3<T> & outVec_2,      
01696         Vector3<T> & outVec_3,      
01697         // O/P: (for translating to force feedback)
01698         Vector3<T> * contactPt,     
01699         // Threshold for zero value
01700         T tolerance = Math<T>::ThresholdZero    
01701 )
01702 {
01703     //--------------------------------------------------------------------
01704     // Transform the cylinder to align with y-axis with c1 at the origin
01705     //
01706     //      __l2__
01707     //         |
01708     //      (0,0,0)
01709     //      ___|__
01710     //        l1
01711     //
01712     Vector3<T> l2( (c2-c1)/2 );
01713     T tCylinderHalfLength = l2.Length();
01714     Vector3<T> vTranslator( l2 + c1 );  // translate the cylinder's center pt at half height to the origin
01715     Matrix3x3<T> rotMat = CreateRotationMatrix3x3FromVectorAtoVectorB(
01716                             l2, VectorY );
01717     l2.SetXYZ(     0,  tCylinderHalfLength, 0 );
01718     Vector3<T> l1( 0, -tCylinderHalfLength, 0 );
01719     //Vector3<T> l1 = rotMat * ( c1 - vTranslator );
01720     //l2 = rotMat * ( c2 - vTranslator );
01721     //--------------------------------------------------------------------
01722     // Transform the triangle with the same transformation for cylinder
01723     Vector3<T> pp( rotMat * ( p - vTranslator ) );
01724     Vector3<T> qq( rotMat * ( q - vTranslator ) );
01725     Vector3<T> rr( rotMat * ( r - vTranslator ) );
01726     //--------------------------------------------------------------------
01727     //--------------------------------------------------------------------
01728     //********************************************************************
01729     //--------------------------------------------------------------------
01730     // Let P1 is the plane containing the triangle
01731     //
01732     //--------------------------------------------------------------------
01733     // Case 1:  Cylinder does not intersect with the triangle 
01734     //          if both vertices of cylinder lie above or below P1
01735     //--------------------------------------------------------------------
01736     // Case 2:  Each vertex of cylinder lies on opposite side of P1
01737     //   Cylinder may intersects with the triangle
01738     //--------------------------------------------------------------------
01739     // Case 3:  One vertex of cylinder lies on one side of P1
01740     //          and the other lies on P1
01741     //   Cylinder may intersects with the triangle
01742     //--------------------------------------------------------------------
01743     // Case 4:  The cylinder is parallel with the plane of the triangle
01744     //          e.g. both c1 and c2 lies on the plane of the triangle
01745     //   Cylinder may intersects with the triangle
01746     //--------------------------------------------------------------------
01747     //********************************************************************
01748     // CASE 1: Both vertices of cylinder lie above or below P1
01749     //--------------------------------------------------------------------
01750     // Reject if all triangle point lies below y-value of l1
01751     T lowValue = -tolerance + l1[1];
01752     if ( pp[1] < lowValue && qq[1] < lowValue && rr[1] < lowValue ) {
01753     //if ( pp[1] < 0 && qq[1] < 0 && rr[1] < 0 ) {
01754         //std::cout << "Reject if all triangle point lies below y=0 (y of c1)\n";
01755         TAPsDebugMessage( "Reject if all triangle point lies below local y of c1\n" );
01756         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01757         return false;
01758     }
01759     //--------------------------------------------------------------------
01760     // Reject if all triangle point lies above y-value of l2
01761     T highValue = tolerance + l2[1];
01762     if ( pp[1] > highValue && qq[1] > highValue && rr[1] > highValue ) {
01763         //std::cout << "Reject if all triangle point lies above y of l2\n";
01764         TAPsDebugMessage( "Reject if all triangle point lies above local y of c2\n" );
01765         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01766         return false;
01767     }
01768     //--------------------------------------------------------------------
01769     //********************************************************************
01770     //--------------------------------------------------------------------
01771     // Find the normal of the triangle
01772     Vector3<T> N = (qq - pp) ^ (rr - pp);
01773     N.Normalized();
01774     //--------------------------------------------------------------------
01775     // Find where vertices of cylinder lie on which side of P1 plane
01776     T Kplane = pp * N;      // Plane Constant
01777     T l1P = N*l1 - Kplane;
01778     T l2P = N*l2 - Kplane;
01779     T zero = Math<T>::ZERO;
01780     //--------------------------------------------------------------------
01781     //********************************************************************
01782     // Case 3: c1 lies on the plane, but c2 does not
01783     //--------------------------------------------------------------------
01784     if ( fabs( l1P ) <= tolerance && fabs( l2P ) > tolerance ) {
01785         //l1P = zero;
01786         //-----------------------------------------------------------
01787         // Case the point is in the triangle
01788         bool result = FindIfAPointIsInATriangleOnTheSamePlane( l1, pp, qq, rr, tolerance );
01789         if ( result ) {
01790 
01791             TAPsDebugMessage( "Case the point L1 is in the triangle\n" );
01792 
01793             // Move the triangle's point if it lies between l2 and l1.
01794             radius += tolerance;
01795             T ratio, distance;
01796             Vector3<T> projectedPt;
01797 
01798             rotMat.Inversed();
01799 
01800             FindProjectedPointOnALine( pp, l2, l1, ratio, projectedPt, distance );
01801             if( 0 <= ratio && ratio <= 1 ) {
01802                 outVec_1 = (rotMat * ( l1 - projectedPt )) + vTranslator;
01803             }
01804             FindProjectedPointOnALine( qq, l2, l1, ratio, projectedPt, distance );
01805             if( 0 <= ratio && ratio <= 1 ) {
01806                 outVec_2 = (rotMat * ( l1 - projectedPt )) + vTranslator;
01807             }
01808             FindProjectedPointOnALine( rr, l2, l1, ratio, projectedPt, distance );
01809             if( 0 <= ratio && ratio <= 1 ) {
01810                 outVec_3 = (rotMat * ( l1 - projectedPt )) + vTranslator;
01811             }
01812 
01813             if ( contactPt ) {
01814                 //std::cout << "Cyn CD# c1 01\n";
01815                 *contactPt = c1;
01816             }
01817             return true;
01818         }
01819         //-----------------------------------------------------------
01820         // Case the point is not in the triangle
01821         // But the point is less than the cylinder radius from the triangle
01822         radius += tolerance;
01823         T ratio, distance;
01824         Vector3<T> projectedPt;
01825         FindProjectedPointOnALine( l1, pp, qq, ratio, projectedPt, distance );
01826         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01827 
01828             TAPsDebugMessage( "Case1 the point L1 is not in the triangle\n" );
01829 
01830             Vector3<T> out( (projectedPt - l1).Normalized() * (radius - distance) );
01831             out = (rotMat.Inversed() * out) + vTranslator;
01832             outVec_1 = outVec_2 = outVec_3 = out;
01833 
01834             if ( contactPt ) {
01835                 //std::cout << "Cyn CD# c1 02\n";
01836                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01837             }
01838 
01839             return true;
01840         }
01841         FindProjectedPointOnALine( l1, qq, rr, ratio, projectedPt, distance );
01842         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01843 
01844             TAPsDebugMessage( "Case2 the point L1 is not in the triangle\n" );
01845 
01846             Vector3<T> out( (projectedPt - l1).Normalized() * (radius - distance) );
01847             out = (rotMat.Inversed() * out) + vTranslator;
01848             outVec_1 = outVec_2 = outVec_3 = out;
01849 
01850             if ( contactPt ) {
01851                 //std::cout << "Cyn CD# c1 03\n";
01852                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01853             }
01854 
01855             return true;
01856         }
01857         FindProjectedPointOnALine( l1, rr, pp, ratio, projectedPt, distance );
01858         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01859 
01860             TAPsDebugMessage( "Case3 the point L1 is not in the triangle\n" );
01861 
01862             Vector3<T> out( (projectedPt - l1).Normalized() * (radius - distance) );
01863             out = (rotMat.Inversed() * out) + vTranslator;
01864             outVec_1 = outVec_2 = outVec_3 = out;
01865 
01866             if ( contactPt ) {
01867                 //std::cout << "Cyn CD# c1 04\n";
01868                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01869             }
01870 
01871             return true;
01872         }
01873         //-----------------------------------------------------------
01874         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01875         return false;
01876     }
01877     //--------------------------------------------------------------------
01878     //********************************************************************
01879     // Case 3: c2 lies on the plane, but c1 does not
01880     //--------------------------------------------------------------------
01881     if ( fabs( l2P ) <= tolerance && fabs( l1P ) > tolerance ) {
01882         //l2P = zero;
01883         //-----------------------------------------------------------
01884         // Case the point is in the triangle
01885         bool result = FindIfAPointIsInATriangleOnTheSamePlane( l2, pp, qq, rr, tolerance );
01886         if ( result ) {
01887 
01888             TAPsDebugMessage( "Case the point L2 is in the triangle\n" );
01889 
01890             // Move the triangle's point if it lies between l2 and l1.
01891             radius += tolerance;
01892             T ratio, distance;
01893             Vector3<T> projectedPt;
01894 
01895             FindProjectedPointOnALine( pp, l2, l1, ratio, projectedPt, distance );
01896             if( 0 <= ratio && ratio <= 1 ) {
01897                 outVec_1 = (rotMat.Inversed() * ( l2 - projectedPt )) + vTranslator;
01898             }
01899             FindProjectedPointOnALine( qq, l2, l1, ratio, projectedPt, distance );
01900             if( 0 <= ratio && ratio <= 1 ) {
01901                 outVec_2 = (rotMat.Inversed() * ( l2 - projectedPt )) + vTranslator;
01902             }
01903             FindProjectedPointOnALine( rr, l2, l1, ratio, projectedPt, distance );
01904             if( 0 <= ratio && ratio <= 1 ) {
01905                 outVec_3 = (rotMat.Inversed() * ( l2 - projectedPt )) + vTranslator;
01906             }
01907 
01908             if ( contactPt ) {
01909                 //std::cout << "Cyn CD# c2 01\n";
01910                 *contactPt = c2;
01911             }
01912             return true;
01913         }
01914         //-----------------------------------------------------------
01915         // Case the point is not in the triangle
01916         radius += tolerance;
01917         T ratio, distance;
01918         Vector3<T> projectedPt;
01919         FindProjectedPointOnALine( l2, pp, qq, ratio, projectedPt, distance );
01920         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01921 
01922             TAPsDebugMessage( "Case1 the point L2 is not in the triangle\n" );
01923 
01924             Vector3<T> out( (projectedPt - l2).Normalized() * (radius - distance) );
01925             out = (rotMat.Inversed() * out) + vTranslator;
01926             outVec_1 = outVec_2 = outVec_3 = out;
01927 
01928             if ( contactPt ) {
01929                 //std::cout << "Cyn CD# c2 02\n";
01930                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01931             }
01932 
01933             return true;
01934         }
01935         FindProjectedPointOnALine( l2, qq, rr, ratio, projectedPt, distance );
01936         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01937 
01938             TAPsDebugMessage( "Case2 the point L2 is not in the triangle\n" );
01939 
01940             Vector3<T> out( (projectedPt - l2).Normalized() * (radius - distance) );
01941             out = (rotMat.Inversed() * out) + vTranslator;
01942             outVec_1 = outVec_2 = outVec_3 = out;
01943 
01944             if ( contactPt ) {
01945                 //std::cout << "Cyn CD# c2 03\n";
01946                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01947             }
01948 
01949             return true;
01950         }
01951         FindProjectedPointOnALine( l2, rr, pp, ratio, projectedPt, distance );
01952         if ( 0 <= ratio && ratio <= 1 && distance <= radius ) {
01953 
01954             TAPsDebugMessage( "Case3 the point L2 is not in the triangle\n" );
01955 
01956             Vector3<T> out( (projectedPt - l2).Normalized() * (radius - distance) );
01957             out = (rotMat.Inversed() * out) + vTranslator;
01958             outVec_1 = outVec_2 = outVec_3 = out;
01959 
01960             if ( contactPt ) {
01961                 //std::cout << "Cyn CD# c2 04\n";
01962                 *contactPt = (rotMat.Inversed() * Vector3<T>( 0, 0, projectedPt[2] )) + vTranslator;
01963             }
01964 
01965             return true;
01966         }
01967         //-----------------------------------------------------------
01968         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01969         return false;
01970     }
01971     //--------------------------------------------------------------------
01972     //********************************************************************
01973     // Case 4: The cylinder is parallel with the plane of triangle
01974     //   e.g. both c1 and c2 lies on the plane of the triangle
01975     //--------------------------------------------------------------------
01976     if ( fabs(l1P - l2P) <= tolerance ) {
01977         T distance;
01978         radius += tolerance;
01979         //-----------------------------------------------------------
01980         // Check l1 distance from plane
01981         Vector3<T> projectedPt1;
01982         FindProjectedPointOnAPlane( l1, pp, N, projectedPt1, distance );
01983         //-----------------------------------------------------------
01984         if ( distance > radius ) {
01985             if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
01986             return false;
01987         }
01988         //-----------------------------------------------------------
01989         // Case the projected point is in the triangle
01990         {
01991             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
01992                                 projectedPt1, pp, qq, rr, tolerance );
01993             if ( result ) {
01994                 TAPsDebugMessage( "Case Parallel: the projected point L1 is in the triangle\n" );
01995 
01996                 Vector3<T> out( (projectedPt1 - l1).Normalized() * (radius - distance) );
01997                 out = (rotMat.Inversed() * out) + vTranslator;
01998                 outVec_1 = outVec_2 = outVec_3 = out;
01999 
02000                 if ( contactPt ) {
02001                     //std::cout << "Cyn CD# (c1&c2 parallel to the tri) c1\n";
02002                     *contactPt = c1;
02003                 }
02004                 return true;
02005             }
02006         }
02007         //-----------------------------------------------------------
02008         // Check l2 distance from plane
02009         Vector3<T> projectedPt2;
02010         FindProjectedPointOnAPlane( l2, pp, N, projectedPt2, distance );
02011         //-----------------------------------------------------------
02012         if ( distance > radius ) {
02013             if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
02014             return false;
02015         }
02016         //-----------------------------------------------------------
02017         // Case the projected point is in the triangle
02018         {
02019             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
02020                                 projectedPt2, pp, qq, rr, tolerance );
02021             if ( result ) {
02022                 TAPsDebugMessage( "Case Parallel: the projected point L2 is in the triangle\n" );
02023 
02024                 Vector3<T> out( (projectedPt2 - l2).Normalized() * (radius - distance) );
02025                 out = (rotMat.Inversed() * out) + vTranslator;
02026                 outVec_1 = outVec_2 = outVec_3 = out;
02027 
02028                 if ( contactPt ) {
02029                     //std::cout << "Cyn CD# (c1&c2 parallel to the tri) c2\n";
02030                     *contactPt = c2;
02031                 }
02032                 return true;
02033             }
02034         }
02035         //-----------------------------------------------------------
02036         // Check if line segment l2-l1 intersects the triangle
02037         T ratio1, ratio2;
02038         bool touching;
02039         if ( FindIntersectionLineSegmentLineSegment( 
02040                 projectedPt1, projectedPt2, pp, qq, ratio1, ratio2, touching, tolerance )
02041         ) {
02042             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle p-q\n" );
02043 
02044             // same as      (projectedPt2 - l2)
02045             Vector3<T> out( (projectedPt1 - l1).Normalized() * (radius - distance) );
02046             out = (rotMat.Inversed() * out) + vTranslator;
02047             outVec_1 = outVec_2 = outVec_3 = out;
02048 
02049             if ( contactPt ) {
02050                 //std::cout << "Cyn CD# (c1&c2 parallel to the tri) (c1+c2)/2 -- 01\n";
02051                 *contactPt = ( c1 + c2 ) * 0.5;
02052             }
02053             return true;
02054         }
02055         if ( FindIntersectionLineSegmentLineSegment( 
02056                 projectedPt1, projectedPt2, qq, rr, ratio1, ratio2, touching, tolerance )
02057         ) {
02058             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle q-r\n" );
02059 
02060             // same as      (projectedPt2 - l2)
02061             Vector3<T> out( (projectedPt1 - l1).Normalized() * (radius - distance) );
02062             out = (rotMat.Inversed() * out) + vTranslator;
02063             outVec_1 = outVec_2 = outVec_3 = out;
02064 
02065             if ( contactPt ) {
02066                 //std::cout << "Cyn CD# (c1&c2 parallel to the tri) (c1+c2)/2 -- 02\n";
02067                 *contactPt = ( c1 + c2 ) * 0.5;
02068             }
02069             return true;
02070         }
02071         if ( FindIntersectionLineSegmentLineSegment( 
02072                 projectedPt1, projectedPt2, rr, pp, ratio1, ratio2, touching, tolerance )
02073         ) {
02074             TAPsDebugMessage( "Case Parallel: line segment L2-L1 intersects the triangle r-p\n" );
02075 
02076             // same as      (projectedPt2 - l2)
02077             Vector3<T> out( (projectedPt1 - l1).Normalized() * (radius - distance) );
02078             out = (rotMat.Inversed() * out) + vTranslator;
02079             outVec_1 = outVec_2 = outVec_3 = out;
02080 
02081             if ( contactPt ) {
02082                 //std::cout << "Cyn CD# (c1&c2 parallel to the tri) (c1+c2)/2 -- 03\n";
02083                 *contactPt = ( c1 + c2 ) * 0.5;
02084             }
02085             return true;
02086         }
02087         //-----------------------------------------------------------
02088         //std::cout << "Case Parallel: line segment L2-L1 DOESN't intersect the triangle\n";
02089         TAPsDebugMessage( "Case Parallel: line segment L2-L1 DOESN't intersect the triangle\n" );
02090         if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );
02091         return false;
02092     }
02093     //--------------------------------------------------------------------
02094     // Case the cylinder is not parallel with the plane of triangle
02095     // and either l1 and l2 of cylinder does not lie on the plane of the triangle
02096     radius += tolerance;
02097     //---------------------------------------------------------------
02098 //  if ( ( l1P > radius && l2P > radius ) || ( l1P < -radius && l2P < -radius ) ) {
02099         //TAPsDebugMessage( "Radius (" << radius << "): " << l1P << " " << l2P << "\n" );
02100         //TAPsDebugMessage( "Case Not Parallel1: cylinder skeleton does not intersect the triangle plane\n" );
02101 //      return false;
02102 //  }
02103     /*
02104     //---------------------------------------------------------------
02105     if (   ( l1P > tolerance && l2P > tolerance ) 
02106         || ( l1P < -tolerance && l2P < -tolerance ) ) {
02107         bool finalResult = false;
02108         //------------------------------------------------------
02109         // Project l1 to the triangle plane
02110         {
02111             Vector3<T> projectedPt1( pp - l1P*N );
02112             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
02113                                 projectedPt1, pp, qq, rr, tolerance );
02114             //---------------------------------------------
02115             // Case the projected point is in the triangle
02116             if ( result ) {
02117                 //std::cout << "Case Not Parallel (--/++): the projected point of l1 is in the triangle\n";
02118                 TAPsDebugMessage( "Case Not Parallel (--/++): the projected point of l1 is in the triangle\n" );
02119                 //return true;
02120                 finalResult = true;
02121             }
02122         }
02123         //------------------------------------------------------
02124         // Project l2 to the triangle plane
02125         {
02126             Vector3<T> projectedPt2( pp - l2P*N );
02127             bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
02128                                 projectedPt2, pp, qq, rr, tolerance );
02129             //---------------------------------------------
02130             // Case the projected point is in the triangle
02131             if ( result ) {
02132                 //std::cout << "Case Not Parallel (--/++): the projected point of l2 is in the triangle\n";
02133                 TAPsDebugMessage( "Case Not Parallel (--/++): the projected point of l2 is in the triangle\n" );
02134                 //return true;
02135                 finalResult = true;
02136             }
02137         }
02138 //      return finalResult;
02139     }
02140     //*/
02141     //--------------------------------------------------------------------
02142     //********************************************************************
02143     // CASE 2: Both vertices of cylinder lie above or below P1
02144     //--------------------------------------------------------------------
02145     if ( ( l1P < -tolerance && l2P >  tolerance ) 
02146       || ( l1P >  tolerance && l2P < -tolerance ) ) {
02147         //------------------------------------------------------
02148         // Find the point on the line that intersects the triangle plane
02149         Vector3<T> l2l1( l2-l1 );
02150         T ratio = (N*(pp-l1)) / (N*l2l1);
02151         Vector3<T> projectedPt( l1 + ratio*l2l1 );
02152         //------------------------------------------------------
02153         bool result = FindIfAPointIsInATriangleOnTheSamePlane( 
02154                             projectedPt, pp, qq, rr, tolerance );
02155         //------------------------------------------------------
02156         // Case the projected point is in the triangle
02157         if ( result ) {
02158 
02159             TAPsDebugMessage( "Case Not Parallel: the triangle intersects the cylinder axis\n" );
02160 
02161             // The out vectors for THIS CASE IS IGNORED!!!
02162             // To implement it the ratio should be converted to length. 
02163             // The length should be compared with the cylinder radius.
02164             // If the length is less than the radius, then move the triangle out 
02165             // from the cylinder top or bottom part.
02166             // Otherwise, move the triangle out from the cylinder axis with 
02167             // the move direction is parallel to the cylinder axis.
02168 
02169             // Move the triangle out with the opposite direction of its normal
02170             outVec_1 = N * radius;
02171             outVec_1 = outVec_2 = outVec_3 = (rotMat.Inversed() * outVec_1);
02172 
02173             if ( contactPt ) {
02174                 //std::cout << "Cyn CD# Triangle intersect the cylinder's axis\n";
02175                 *contactPt = (rotMat * projectedPt) + vTranslator;  // rotMat is already inversed
02176             }
02177             return true;
02178         }
02179     }
02180     //====================================================================
02181     // Final Test
02182     //---------------------------------------------------------------
02183     // Case the projected point is NOT in the triangle
02184     T distance1, distance2, distance3;
02185     Vector3<T> contactNormal1, contactNormal2, contactNormal3;
02186     Vector3<T> projPtOnCylAxis, projPtOnATriEdge;
02187     bool result = false;
02188 
02189     outVec_1 = outVec_2 = outVec_3 = ZeroVector;
02190 
02191     FindClosestDistanceBetweenTwoLineSegments( 
02192                 l1, l2,         // I/P: a line 
02193                 pp, qq,         // I/P: the pq edge of the triangle
02194                 distance1,      // O/P: distance
02195                 contactNormal1, // O/P: contact normal
02196                 projPtOnCylAxis, 
02197                 projPtOnATriEdge, 
02198                 tolerance );
02199     distance1 = radius - distance1;
02200 
02201     if ( contactPt )    (*contactPt).SetXYZ( 0, 0, 0 );     // clear the contact point
02202 
02203     rotMat.Inversed();      // inverse the rotation matrix
02204 
02205     if ( distance1 >= 0 ) {
02206 
02207         TAPsDebugMessage( "CASE: distance1 >= 0" );
02208 
02209         //Vector3<T> dir( projPtOnATriEdge - projPtOnCylAxis );
02210         Vector3<T> dir( projPtOnCylAxis - projPtOnATriEdge );
02211         //dir = ((rotMat * dir) + vTranslator).Normalized() * distance1;
02212         dir = dir.Normalized() * distance1;
02213         outVec_1 = dir;
02214         outVec_2 = dir;
02215 
02216         if ( contactPt ) {
02217             //std::cout << "Cyn CD# Final Test -- 01\n";
02218             *contactPt += (rotMat * projPtOnCylAxis) + vTranslator;
02219         }
02220         result = true;
02221     }
02222 
02223     FindClosestDistanceBetweenTwoLineSegments( 
02224                 l1, l2,         // I/P: a line 
02225                 qq, rr,         // I/P: the pq edge of the triangle
02226                 distance2,      // O/P: distance
02227                 contactNormal2, // O/P: contact normal
02228                 projPtOnCylAxis, 
02229                 projPtOnATriEdge, 
02230                 tolerance );
02231     distance2 = radius - distance2;
02232     if ( distance2 >= 0 ) {
02233 
02234         TAPsDebugMessage( "CASE: distance2 >= 0" );
02235 
02236         //Vector3<T> dir( projPtOnATriEdge - projPtOnCylAxis );
02237         Vector3<T> dir( projPtOnCylAxis - projPtOnATriEdge );
02238         //dir = ((rotMat * dir) + vTranslator).Normalized() * distance2;
02239         dir = dir.Normalized() * distance2;
02240         outVec_2 = dir;
02241         outVec_3 = dir;
02242 
02243         if ( contactPt ) {
02244             //std::cout << "Cyn CD# Final Test -- 02\n";
02245             *contactPt += (rotMat * projPtOnCylAxis) + vTranslator;
02246         }
02247         result = true;
02248     }
02249 
02250     FindClosestDistanceBetweenTwoLineSegments( 
02251                 l1, l2,         // I/P: a line 
02252                 rr, pp,         // I/P: the pq edge of the triangle
02253                 distance3,      // O/P: distance
02254                 contactNormal3, // O/P: contact normal
02255                 projPtOnCylAxis, 
02256                 projPtOnATriEdge, 
02257                 tolerance );
02258     distance3 = radius - distance3;
02259     if ( distance3 >= 0 ) {
02260 
02261         TAPsDebugMessage( "CASE: distance3 >= 0" );
02262 
02263         //Vector3<T> dir( projPtOnATriEdge - projPtOnCylAxis );
02264         Vector3<T> dir( projPtOnCylAxis - projPtOnATriEdge );
02265         //dir = ((rotMat * dir) + vTranslator).Normalized() * distance3;
02266         dir = dir.Normalized() * distance3;
02267         outVec_1 = dir;
02268         outVec_3 = dir;
02269 
02270         if ( contactPt ) {
02271             //std::cout << "Cyn CD# Final Test -- 03\n";
02272             *contactPt += (rotMat * projPtOnCylAxis) + vTranslator;
02273         }
02274         result = true;
02275     }
02276 
02277     if ( distance1 >= 0 && distance3 >= 0 ) {
02278         outVec_1 *= 0.5;
02279         if ( contactPt ) {
02280             *contactPt *= 0.5;
02281         }
02282     }
02283     if ( distance1 >= 0 && distance2 >= 0 ) {
02284         outVec_2 *= 0.5;
02285         if ( contactPt ) {
02286             *contactPt *= 0.5;
02287         }
02288     }
02289     if ( distance2 >= 0 && distance3 >= 0 ) {
02290         outVec_3 *= 0.5;
02291         if ( contactPt ) {
02292             *contactPt *= 0.5;
02293         }
02294     }
02295 
02296     return result;
02297 }
02298 // END: FindIntersectionCylinderTriangle W/ Outputs
02299 //-----------------------------------------------------------------------------
02300 
02301 
02302 
02303 
02304 //*****************************************************************************
02305 // Find Triangle-Triangle Intersection
02306 // I/P: three vectors defining first triangle in counter-clockwise dir
02307 // I/P: three vectors defining second triangle in counter-clockwise dir
02308 // O/P: a closest distance
02309 //*****************************************************************************
02310 template <typename T>
02311 bool CGMath<T>::FindIntersectionTriangleTriangle (
02312         Vector3<T> const & p1,      // first triangle
02313         Vector3<T> const & q1, 
02314         Vector3<T> const & r1, 
02315         Vector3<T> const & p2,      // second triangle
02316         Vector3<T> const & q2, 
02317         Vector3<T> const & r2, 
02318         T tolerance = Math<T>::ThresholdZero
02319 )
02320 {
02321     T zero = Math<T>::ZERO;
02322     //--------------------------------------------------------------------
02323     // Find the normal of triangle#2
02324     Vector3<T> N2 = (q2 - p2) ^ (r2 - p2);
02325     N2.Normalized();
02326     //--------------------------------------------------------------------
02327     // Find where vertices of triangle#1 lie on which side of P2
02328     T p1P2 = N2 * (p1 - p2);
02329     T q1P2 = N2 * (q1 - p2);
02330     T r1P2 = N2 * (r1 - p2);
02331     if ( fabs( p1P2 ) < tolerance ) p1P2 = zero;
02332     if ( fabs( q1P2 ) < tolerance ) q1P2 = zero;
02333     if ( fabs( r1P2 ) < tolerance ) r1P2 = zero;
02334     if ( p1P2 > zero && q1P2 > zero && r1P2 > zero )    return false;
02335     if ( p1P2 < zero && q1P2 < zero && r1P2 < zero )    return false;
02336     //--------------------------------------------------------------------
02337     // Find the normal of triangle#1
02338     Vector3<T> N1 = (q1 - p1) ^ (r1 - p1);
02339     N1.Normalized();
02340     //--------------------------------------------------------------------
02341     // Find where vertices of triangle#2 lie on which side of P1
02342     T p2P1 = N1 * (p2 - p1);
02343     T q2P1 = N1 * (q2 - p1);
02344     T r2P1 = N1 * (r2 - p1);
02345     if ( fabs( p2P1 ) < tolerance ) p2P1 = zero;
02346     if ( fabs( q2P1 ) < tolerance ) q2P1 = zero;
02347     if ( fabs( r2P1 ) < tolerance ) r2P1 = zero;
02348     //--------------------------------------------------------------------
02349     Vector3<T> const * V2[3];
02350     int caseNo = 0;
02351     // Case p2P1 > zero
02352     if      ( p2P1 > zero ) {
02353         if      ( q2P1 > zero ) {
02354             if      ( r2P1 > zero ) {
02355                 // No Intersection: +p2P1, +q2P1, +r2P1
02356                 return false;
02357             }
02358             else if ( r2P1 < zero ) {
02359                 // Case 1: +p2P1, +q2P1, -r2P1
02360                 caseNo = 1;
02361                 V2[0] = &p2;
02362                 V2[1] = &q2;
02363                 V2[2] = &r2;
02364             }
02365             else {
02366                 // Case 2: +p2P1, +q2P1, 0r2P1
02367                 caseNo = 2;
02368                 V2[0] = &r2;
02369                 V2[1] = &p2;
02370                 V2[2] = &q2;
02371             }
02372         }
02373         else if ( q2P1 < zero ) {
02374             if      ( r2P1 > zero ) {
02375                 // Case 1: +p2P1, -q2P1, +r2P1
02376                 caseNo = 1;
02377                 V2[0] = &r2;
02378                 V2[1] = &p2;
02379                 V2[2] = &q2;
02380             }
02381             else if ( r2P1 < zero ) {
02382                 // Case 1: +p2P1, -q2P1, -r2P1
02383                 caseNo = 1;
02384                 V2[0] = &q2;
02385                 V2[1] = &r2;
02386                 V2[2] = &p2;
02387             }
02388             else {
02389                 // Case 3: +p2P1, -q2P1, 0r2P1
02390                 caseNo = 3;
02391                 V2[0] = &r2;
02392                 V2[1] = &p2;
02393                 V2[2] = &q2;
02394             }
02395         }
02396         else {
02397             if      ( r2P1 > zero ) {
02398                 // Case 2: +p2P1, 0q2P1, +r2P1
02399                 caseNo = 2;
02400                 V2[0] = &q2;
02401                 V2[1] = &r2;
02402                 V2[2] = &p2;
02403             }
02404             else if ( r2P1 < zero ) {
02405                 // Case 3: +p2P1, 0q2P1, -r2P1
02406                 caseNo = 3;
02407                 V2[0] = &q2;
02408                 V2[1] = &r2;
02409                 V2[2] = &p2;
02410             }
02411             else {
02412                 // Case 4: +p2P1, 0q2P1, 0r2P1
02413                 caseNo = 4;
02414                 V2[0] = &q2;
02415                 V2[1] = &r2;
02416                 V2[2] = &p2;
02417             }
02418         }
02419     }
02420     //--------------------------------------------------------------------
02421     // Case p2P1 < zero
02422     else if ( p2P1 < zero ) {
02423         if      ( q2P1 < zero ) {
02424             if      ( r2P1 < zero ) {
02425                 // No Intersection: -p2P1, -q2P1, -r2P1
02426                 return false;
02427             }
02428             else if ( r2P1 > zero ) {
02429                 // Case 1: -p2P1, -q2P1, +r2P1
02430                 caseNo = 1;
02431                 V2[0] = &p2;
02432                 V2[1] = &q2;
02433                 V2[2] = &r2;
02434             }
02435             else {
02436                 // Case 2: -p2P1, -q2P1, 0r2P1
02437                 caseNo = 2;
02438                 V2[0] = &r2;
02439                 V2[1] = &p2;
02440                 V2[2] = &q2;
02441             }
02442         }
02443         else if ( q2P1 > zero ) {
02444             if      ( r2P1 < zero ) {
02445                 // Case 1: -p2P1, +q2P1, -r2P1
02446                 caseNo = 1;
02447                 V2[0] = &r2;
02448                 V2[1] = &p2;
02449                 V2[2] = &q2;
02450             }
02451             else if ( r2P1 > zero ) {
02452                 // Case 1: -p2P1, +q2P1, +r2P1
02453                 caseNo = 1;
02454                 V2[0] = &q2;
02455                 V2[1] = &r2;
02456                 V2[2] = &p2;
02457             }
02458             else {
02459                 // Case 3: -p2P1, +q2P1, 0r2P1
02460                 caseNo = 3;
02461                 V2[0] = &r2;
02462                 V2[1] = &p2;
02463                 V2[2] = &q2;
02464             }
02465         }
02466         else {
02467             if      ( r2P1 < zero ) {
02468                 // Case 2: -p2P1, 0q2P1, -r2P1
02469                 caseNo = 2;
02470                 V2[0] = &q2;
02471                 V2[1] = &r2;
02472                 V2[2] = &p2;
02473             }
02474             else if ( r2P1 > zero ) {
02475                 // Case 3: -p2P1, 0q2P1, +r2P1
02476                 caseNo = 3;
02477                 V2[0] = &q2;
02478                 V2[1] = &r2;
02479                 V2[2] = &p2;
02480             }
02481             else {
02482                 // Case 4: -p2P1, 0q2P1, 0r2P1
02483                 caseNo = 4;
02484                 V2[0] = &q2;
02485                 V2[1] = &r2;
02486                 V2[2] = &p2;
02487             }
02488         }
02489     }
02490     //--------------------------------------------------------------------
02491     // Case p2P1 = zero
02492     else {
02493         if      ( q2P1 < zero ) {
02494             if      ( r2P1 < zero ) {
02495                 // Case 2: 0p2P1, -q2P1, -r2P1
02496                 caseNo = 2;
02497                 V2[0] = &p2;
02498                 V2[1] = &q2;
02499                 V2[2] = &r2;
02500             }
02501             else if ( r2P1 > zero ) {
02502                 // Case 3: 0p2P1, -q2P1, +r2P1
02503                 caseNo = 3;
02504                 V2[0] = &p2;
02505                 V2[1] = &q2;
02506                 V2[2] = &r2;
02507             }
02508             else {
02509                 // Case 4: 0p2P1, -q2P1, 0r2P1
02510                 caseNo = 4;
02511                 V2[0] = &r2;
02512                 V2[1] = &p2;
02513                 V2[2] = &q2;
02514             }
02515         }
02516         else if ( q2P1 > zero ) {
02517             if      ( r2P1 < zero ) {
02518                 // Case 3: 0p2P1, +q2P1, -r2P1
02519                 caseNo = 3;
02520                 V2[0] = &p2;
02521                 V2[1] = &q2;
02522                 V2[2] = &r2;
02523             }
02524             else if ( r2P1 > zero ) {
02525                 // Case 2: 0p2P1, +q2P1, +r2P1
02526                 caseNo = 2;
02527                 V2[0] = &p2;
02528                 V2[1] = &q2;
02529                 V2[2] = &r2;
02530             }
02531             else {
02532                 // Case 4: 0p2P1, +q2P1, 0r2P1
02533                 caseNo = 4;
02534                 V2[0] = &r2;
02535                 V2[1] = &p2;
02536                 V2[2] = &q2;
02537             }
02538         }
02539         else {
02540             if      ( r2P1 < zero ) {
02541                 // Case 4: 0p2P1, 0q2P1, -r2P1
02542                 caseNo = 4;
02543                 V2[0] = &p2;
02544                 V2[1] = &q2;
02545                 V2[2] = &r2;
02546             }
02547             else if ( r2P1 > zero ) {
02548                 // Case 4: 0p2P1, 0q2P1, +r2P1
02549                 caseNo = 4;
02550                 V2[0] = &p2;
02551                 V2[1] = &q2;
02552                 V2[2] = &r2;
02553             }
02554             else {
02555                 // Case 5: 0p2P1, 0q2P1, 0r2P1
02556                 caseNo = 5;
02557             }
02558         }
02559     }
02560     //--------------------------------------------------------------------
02561     // Case 1:  Two vertices of triangle#2 lie on one side of P1
02562     //          and the other lies on the other side of P1
02563     //          //Two vertices of triangle#1 lie on one side of P2
02564     //          //and the other lies on the other side of P2
02565     //  Triangle#2 may intersects with triangle#1
02566     //--------------------------------------------------------------------
02567     // Case 2:  Two vertices of triangle#2 lie on one side of P1
02568     //          and the other lies on P1
02569     //          //Two vertices of triangle#1 lie on one side of P2
02570     //          //and the other lies on the other side of P2
02571     //  A vertex of triangle#2 may touches interior/boundary of triangle#1
02572     //--------------------------------------------------------------------
02573     // Case 3:  One vertex of triangle#2 lies on one side of P1, 
02574     //          another one lies on the other side of P1, 
02575     //          and the last one lies on P1
02576     //          //Two vertices of triangle#1 lie on one side of P2
02577     //          //and the other lies on the other side of P2
02578     //  A vertex of triangle#2 may touches interior/boundary of triangle#1
02579     //--------------------------------------------------------------------
02580     // Case 4:  One vertex of triangle#2 lies on one side of P1
02581     //          and the other two lie on P1
02582     //          //Two vertices of triangle#1 lie on one side of P2
02583     //          //and the other lies on the other side of P2
02584     //  An edge of Triangle#2 may intersects or touches triangle#1
02585     //--------------------------------------------------------------------
02586     // Case 5:  All three vertices of triangle#2 lies on P1
02587     //          Also all three vertices of triangle#1 (should) lies on P2
02588     //  Triangle#2 and triangle#1 are coplanar
02589     //  Triangle#2 may intersects with triangle#1
02590     //--------------------------------------------------------------------
02591     //Vector3<T> D( N1 ^ N2 );      // The direction of intersection line
02592     T t2[2];            // 
02593     T D1;               // with N1 define plane1 -- D1 = N1*(any_pt_on_P1)
02594     Vector3<T> proj2[2];
02595     Vector3<T> diff[2];
02596     Vector3<T> intersectionPt[4];
02597     bool result1, result2, result3;
02598     T para1, para2;
02599     bool touching;
02600     int count;
02601     switch ( caseNo ) {
02602         //===========================================================
02603         // *V2[0] and *V2[1] lie on one side of P1 plane
02604         // *V2[2] lies on the other side of P1 plane
02605         case 1:
02606             //std::cout << "Case1\n";
02607             //--------------------------------------------------
02608             // Project onto P1 plane
02609             D1 = N1 * p1;
02610             diff[0] = *V2[2] - *V2[0];
02611             diff[1] = *V2[2] - *V2[1];
02612             t2[0] = ( D1 - N1*(*V2[0]) ) / ( N1*diff[0] );
02613             t2[1] = ( D1 - N1*(*V2[1]) ) / ( N1*diff[1] );
02614             proj2[0] = *V2[0] + t2[0]*diff[0];
02615             proj2[1] = *V2[1] + t2[1]*diff[1];
02616             //--------------------------------------------------
02617             // Test if points are inside Triangle#1
02618             result1 = FindIfAPointIsInATriangleOnTheSamePlane( proj2[0], p1, q1, r1, tolerance );
02619             result2 = FindIfAPointIsInATriangleOnTheSamePlane( proj2[1], p1, q1, r1, tolerance );
02620             //glPointSize( 9 );
02621             //glBegin( GL_POINTS );
02622             //  if ( result1 )  {
02623             //      glColor3f( 0, 0, 0 );
02624             //  }
02625             //  else {
02626             //      glColor3f( 0.5, 0.5, 1 );
02627             //  }
02628             //  glVertex3fv( &(proj2[0].GetDataFloat()) );
02629             //  if ( result2 )  {
02630             //      glColor3f( 0, 0, 0 );
02631             //  }
02632             //  else {
02633             //      glColor3f( 0.5, 0.5, 1 );
02634             //  }
02635             //  glVertex3fv( &(proj2[1].GetDataFloat()) );
02636             //glEnd();
02637             //glPointSize( 1 );
02638             //--------------------------------------------------
02639             // At least one of the projected points is inside Triangle#1
02640             if ( result1 || result2 ) {
02641                 //std::cout << "RESULT1 & 2: " << result1 << "\t" << result2 << "\n";
02642                 return true;
02643             }
02644             //--------------------------------------------------
02645             // Both projected points are outside Triangle#1
02646             else {
02647                 count = 0;
02648                 result1 = FindIntersectionLineSegmentLineSegment( 
02649                     proj2[0], proj2[1], p1, q1, para1, para2, touching, tolerance );
02650                 result2 = FindIntersectionLineSegmentLineSegment( 
02651                     proj2[0], proj2[1], q1, r1, para1, para2, touching, tolerance );
02652                 result3 = FindIntersectionLineSegmentLineSegment( 
02653                     proj2[0], proj2[1], r1, q1, para1, para2, touching, tolerance );
02654                 if ( result1 ) ++count;
02655                 if ( result2 ) ++count;
02656                 if ( result3 ) ++count;
02657                 if ( count >= 2 ) return true;
02658                 //-----------------------------------------
02659                 // Case one point of p1, coplanar with P2
02660                 else {
02661                     if ( p1P2 == zero ) {
02662                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( p1, p2, q2, r2, tolerance );
02663                         if ( result1 )  return true;
02664                     }
02665                     if ( q1P2 == zero ) {
02666                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( q1, p2, q2, r2, tolerance );
02667                         if ( result1 )  return true;
02668                     }
02669                     if ( r1P2 == zero ) {
02670                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( r1, p2, q2, r2, tolerance );
02671                         if ( result1 )  return true;
02672                     }
02673                 }
02674             }
02675             //--------------------------------------------------
02676             return false;
02677             break;
02678         //===========================================================
02679         // *V2[2] is on the P1 plane
02680         // *V2[0] and *V2[1] are on one side of P1 plane
02681         case 2:
02682             //std::cout << "Case2\n";
02683             //--------------------------------------------------
02684             result1 = FindIfAPointIsInATriangleOnTheSamePlane( *V2[0], p1, q1, r1, tolerance );
02685             //glPointSize( 9 );
02686             //glBegin( GL_POINTS );
02687             //  if ( result1 )  {
02688             //      glColor3f( 0, 0, 0 );
02689             //  }
02690             //  else {
02691             //      glColor3f( 0.5, 0.5, 1 );
02692             //  }
02693             //  glVertex3fv( &((*V2[0]).GetDataFloat()) );
02694             //glEnd();
02695             //glPointSize( 1 );
02696             if ( result1 )  return true;
02697             else            return false;
02698             //--------------------------------------------------
02699             break;
02700         //===========================================================
02701         // *V2[0] is on the P1 plane
02702         // *V2[1] lies on one side of P1 plane
02703         // *V2[2] lies on the other side of P1 plane
02704         case 3:
02705             //std::cout << "Case3\n";
02706             //--------------------------------------------------
02707             // Project onto P1 plane
02708             D1 = N1 * p1;
02709             diff[0] = *V2[2] - *V2[1];
02710             t2[0] = ( D1 - N1*(*V2[1]) ) / ( N1*diff[0] );
02711             proj2[0] = *V2[1] + t2[0]*diff[0];
02712             //--------------------------------------------------
02713             // Test if points are inside Triangle#1
02714             result1 = FindIfAPointIsInATriangleOnTheSamePlane( *V2[0], p1, q1, r1, tolerance );
02715             result2 = FindIfAPointIsInATriangleOnTheSamePlane( proj2[0], p1, q1, r1, tolerance );
02716             //glPointSize( 9 );
02717             //glBegin( GL_POINTS );
02718             //  if ( result1 )  {
02719             //      glColor3f( 0, 0, 0 );
02720             //  }
02721             //  else {
02722             //      glColor3f( 0.5, 0.5, 1 );
02723             //  }
02724             //  glVertex3fv( &((*V2[0]).GetDataFloat()) );
02725             //  if ( result2 )  {
02726             //      glColor3f( 0, 0, 0 );
02727             //  }
02728             //  else {
02729             //      glColor3f( 0.5, 0.5, 1 );
02730             //  }
02731             //  glVertex3fv( &(proj2[0].GetDataFloat()) );
02732 
02733             //  glColor3f( 1, 0, 0 );
02734             //  glVertex3fv( &((*V2[1]).GetDataFloat()) );
02735             //  glVertex3fv( &((*V2[2]).GetDataFloat()) );
02736             //glEnd();
02737             //glPointSize( 1 );
02738             //--------------------------------------------------
02739             // At least one of the projected points is inside Triangle#1
02740             if ( result1 || result2 ) {
02741                 //std::cout << "RESULT1 & 2: " << result1 << "\t" << result2 << "\n";
02742                 return true;
02743             }
02744             //--------------------------------------------------
02745             // Both projected points are outside Triangle#1
02746             else {
02747                 count = 0;
02748                 result1 = FindIntersectionLineSegmentLineSegment( 
02749                     *V2[0], proj2[0], p1, q1, para1, para2, touching, tolerance );
02750                 result2 = FindIntersectionLineSegmentLineSegment( 
02751                     *V2[0], proj2[0], q1, r1, para1, para2, touching, tolerance );
02752                 result3 = FindIntersectionLineSegmentLineSegment( 
02753                     *V2[0], proj2[0], r1, q1, para1, para2, touching, tolerance );
02754                 if ( result1 ) ++count;
02755                 if ( result2 ) ++count;
02756                 if ( result3 ) ++count;
02757                 if ( count >= 2 ) return true;
02758                 //-----------------------------------------
02759                 // Case one point of p1, coplanar with P2
02760                 else {
02761                     if ( p1P2 == zero ) {
02762                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( p1, p2, q2, r2, tolerance );
02763                         if ( result1 )  return true;
02764                     }
02765                     if ( q1P2 == zero ) {
02766                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( q1, p2, q2, r2, tolerance );
02767                         if ( result1 )  return true;
02768                     }
02769                     if ( r1P2 == zero ) {
02770                         result1 = FindIfAPointIsInATriangleOnTheSamePlane( r1, p2, q2, r2, tolerance );
02771                         if ( result1 )  return true;
02772                     }
02773                 }
02774             }
02775             //--------------------------------------------------
02776             return false;
02777             break;
02778         //===========================================================
02779         // *V2[0] and *V2[1] lie on P1 plane
02780         // *V2[2] lies on one side of P1 plane
02781         case 4:
02782             //std::cout << "Case4\n";
02783             //--------------------------------------------------
02784             // Test if points are inside Triangle#1
02785             result1 = FindIfAPointIsInATriangleOnTheSamePlane( *V2[0], p1, q1, r1, tolerance );
02786             result2 = FindIfAPointIsInATriangleOnTheSamePlane( *V2[1], p1, q1, r1, tolerance );
02787             //glPointSize( 9 );
02788             //glBegin( GL_POINTS );
02789             //  if ( result1 )  {
02790             //      glColor3f( 0, 0, 0 );
02791             //  }
02792             //  else {
02793             //      glColor3f( 0.5, 0.5, 1 );
02794             //  }
02795             //  glVertex3fv( &((*V2[0]).GetDataFloat()) );
02796             //  if ( result2 )  {
02797             //      glColor3f( 0, 0, 0 );
02798             //  }
02799             //  else {
02800             //      glColor3f( 0.5, 0.5, 1 );
02801             //  }
02802             //  glVertex3fv( &((*V2[1]).GetDataFloat()) );
02803             //glEnd();
02804             //glPointSize( 1 );
02805             //--------------------------------------------------
02806             // At least one of the projected points is inside Triangle#1
02807             if ( result1 || result2 ) {
02808                 return true;
02809             }
02810             //--------------------------------------------------
02811             // Both projected points are outside Triangle#1
02812             else {
02813                 count = 0;
02814                 result1 = FindIntersectionLineSegmentLineSegment( 
02815                     *V2[0], *V2[1], p1, q1, para1, para2, touching, tolerance );
02816                 result2 = FindIntersectionLineSegmentLineSegment( 
02817                     *V2[0], *V2[1], q1, r1, para1, para2, touching, tolerance );
02818                 result3 = FindIntersectionLineSegmentLineSegment( 
02819                     *V2[0], *V2[1], r1, q1, para1, para2, touching, tolerance );
02820                 if ( result1 ) ++count;
02821                 if ( result2 ) ++count;
02822                 if ( result3 ) ++count;
02823                 if ( count >= 2 ) return true;
02824             }
02825             //--------------------------------------------------
02826             break;
02827         //===========================================================
02828         // *V2[0], *V2[1], and *V2[2] lie on P1 plane
02829         // The two triangles are coplanar
02830         case 5:
02831             //std::cout << "Case5\n";
02832             // SHOULD USE TWO DIMENSION INTERSECTION TEST FOR EFFICIENCY
02833             //--------------------------------------------------
02834             // Test if any point of Triangle#2 is inside Triangle#1
02835             result1 = FindIfAPointIsInATriangleOnTheSamePlane( p2, p1, q1, r1, tolerance );
02836             result2 = FindIfAPointIsInATriangleOnTheSamePlane( q2, p1, q1, r1, tolerance );
02837             result3 = FindIfAPointIsInATriangleOnTheSamePlane( r2, p1, q1, r1, tolerance );
02838             if ( result1 || result2 || result3 )    return true;
02839             else {
02840                 //-----------------------------------------
02841                 // Test if any point of Triangle#1 is inside Triangle#2
02842                 result1 = FindIfAPointIsInATriangleOnTheSamePlane( p1, p2, q2, r2, tolerance );
02843                 result2 = FindIfAPointIsInATriangleOnTheSamePlane( q1, p2, q2, r2, tolerance );
02844                 result3 = FindIfAPointIsInATriangleOnTheSamePlane( r1, p2, q2, r2, tolerance );
02845                 if ( result1 || result2 || result3 )    return true;
02846                 else {
02847                     //--------------------------------
02848                     // Test if any edge of Triangle#2 intersects any edge of Triangle#1
02849                     //---------------------------
02850                     // Edge pq of Triangle#2
02851                     result1 = FindIntersectionLineSegmentLineSegment( 
02852                         p2, q2, p1, q1, para1, para2, touching, tolerance );
02853                     if ( result1 )  return true;
02854                     result2 = FindIntersectionLineSegmentLineSegment( 
02855                         p2, q2, q1, r1, para1, para2, touching, tolerance );
02856                     if ( result2 )  return true;
02857                     result3 = FindIntersectionLineSegmentLineSegment( 
02858                         p2, q2, r1, q1, para1, para2, touching, tolerance );
02859                     if ( result3 )  return true;
02860                     //---------------------------
02861                     // Edge qr of Triangle#2
02862                     result1 = FindIntersectionLineSegmentLineSegment( 
02863                         q2, r2, p1, q1, para1, para2, touching, tolerance );
02864                     if ( result1 )  return true;
02865                     result2 = FindIntersectionLineSegmentLineSegment( 
02866                         q2, r2, q1, r1, para1, para2, touching, tolerance );
02867                     if ( result2 )  return true;
02868                     result3 = FindIntersectionLineSegmentLineSegment( 
02869                         q2, r2, r1, q1, para1, para2, touching, tolerance );
02870                     if ( result3 )  return true;
02871                     //---------------------------
02872                     // Edge rp of Triangle#2
02873                     result1 = FindIntersectionLineSegmentLineSegment( 
02874                         r2, p2, p1, q1, para1, para2, touching, tolerance );
02875                     if ( result1 )  return true;
02876                     result2 = FindIntersectionLineSegmentLineSegment( 
02877                         r2, p2, q1, r1, para1, para2, touching, tolerance );
02878                     if ( result2 )  return true;
02879                     result3 = FindIntersectionLineSegmentLineSegment( 
02880                         r2, p2, r1, q1, para1, para2, touching, tolerance );
02881                     if ( result3 )  return true;
02882                 }
02883             }
02884             //--------------------------------------------------
02885             return false;
02886             break;
02887         //===========================================================
02888         default:
02889             std::cout << "Shouldn't reach this case!" << std::endl;
02890             assert( false );
02891             break;
02892     }
02893     return false;
02894 }
02895 //-----------------------------------------------------------------------------
02896 
02897 //*****************************************************************************
02898 // Find if a circle intersects a Triangle
02899 // (Assume the circle center lies on the triangle plane)
02900 // I/P: a vector (center) and a scalar (radius) defining a circle on the triangle plane
02901 // I/P: three vectors defining a triangle in counter-clockwise direction
02902 // O/P: a closest distance (not implemented yet)
02903 // REMARK: This fn is used by FindIntersectionSphereTriangle fn
02904 //*****************************************************************************
02905 template <typename T>
02906 int CGMath<T>::FindIfACircleIntersectsATriangleOnTheSamePlane (
02907         Vector3<T> const & circleCenter,        
02908         T          const & circleRadius,        
02909         Vector3<T> const & p,                   
02910         Vector3<T> const & q,                   
02911         Vector3<T> const & r,                   
02912         T tolerance = Math<T>::ThresholdZero    
02913 )
02914 {
02915     //                \      /
02916     //                 \    /
02917     //                  \  /
02918     //                   \/
02919     //                   /\r
02920     //                  /  \
02921     // qResult := true /    \  pResult := true if line(p,pt) doesn't intersect line(q,r)
02922     //                / Tri  \
02923     // _____________ /________\_________________
02924     //              /p         \q
02925     //             /            \
02926     //            /              \
02927     //           /                \
02928     //          / rResult := true if line(r,pt) doesn't intersect line(p,q)
02929     //
02930     // qResult := true if line(q,pt) doesn't interscet line(r,p)
02931     //--------------------------------------------------------------------
02932     // CASE: the circle intersect a line of triangle
02933     //  - Find the closest point
02934     //  - The closest point must be within the circle radius from the circle center
02935     //  - Find if the point lies on the line of triangle (within the circle radius)
02936     Vector3<T> projPt;
02937     T ratio, distance;
02938     {
02939         FindProjectedPointOnALine( circleCenter, p, q, ratio, projPt, distance );
02940         if ( distance <= circleRadius ) {
02941             Vector3<T> pq( p-q );
02942             Vector3<T> ptp( (projPt-p) );
02943             if ( (ptp^pq).Length() < tolerance ) {
02944                 T LEN = pq.Length() + sqrt( circleRadius*circleRadius - distance*distance );
02945                 T len1 = ptp.Length();
02946                 T len2 = (projPt-q).Length();
02947                 if ( len1 <= LEN && len2 <= LEN ) {
02948                     return 1;
02949                 }
02950                 else {
02951                     return 0;
02952                 }
02953             }
02954         }
02955     }
02956     {
02957         FindProjectedPointOnALine( circleCenter, q, r, ratio, projPt, distance );
02958         if ( distance <= circleRadius ) {
02959             Vector3<T> qr( q-r );
02960             Vector3<T> ptq( (projPt-q) );
02961             if ( (ptq^qr).Length() < tolerance ) {
02962                 T LEN = qr.Length() + sqrt( circleRadius*circleRadius - distance*distance );
02963                 T len1 = ptq.Length();
02964                 T len2 = (projPt-r).Length();
02965                 if ( len1 <= LEN && len2 <= LEN ) {
02966                     return 2;
02967                 }
02968                 else {
02969                     return 0;
02970                 }
02971             }
02972         }
02973     }
02974     {
02975         FindProjectedPointOnALine( circleCenter, r, p, ratio, projPt, distance );
02976         if ( distance <= circleRadius ) {
02977             Vector3<T> rp( r-p );
02978             Vector3<T> ptr( (projPt-r) );
02979             if ( (ptr^rp).Length() < tolerance ) {
02980                 T LEN = rp.Length() + sqrt( circleRadius*circleRadius - distance*distance );
02981                 T len1 = ptr.Length();
02982                 T len2 = (projPt-p).Length();
02983                 if ( len1 <= LEN && len2 <= LEN ) {
02984                     return 3;
02985                 }
02986                 else {
02987                     return 0;
02988                 }
02989             }
02990         }
02991     }
02992     //--------------------------------------------------------------------
02993     // CASE: the circle is completely inside or outside of the triangle
02994     //
02995     // Remark: The first case above made a complete sweep of the circle 
02996     //         inside and outside around the triangle.
02997     //
02998     //         center triangle is the original triangle
02999     //         outer  triangle is the triangle from sweeping the circle around outside the triangle
03000     //         inner  triangle is the triangle from sweeping the circle around inside  the triangle
03001     //
03002     //                 /\
03003     //                /  \
03004     //               / /\ \
03005     //              / /  \ \
03006     //             / / /\ \ \
03007     //            / / /__\ \ \
03008     //           / /________\ \ 
03009     //          /______________\
03010     //
03011     //         So if the circle is within circle radius from the triangle, 
03012     //         then the first case will return true.
03013     //
03014     // Therefore, the computation below will be similar to compute with the inner triangle.
03015     T t1, t2;
03016     bool pTouching, qTouching, rTouching;
03017     bool pResult = FindIntersectionLineSegmentLineSegment( p, circleCenter, q, r, t1, t2, pTouching, tolerance );
03018     bool qResult = FindIntersectionLineSegmentLineSegment( q, circleCenter, r, p, t1, t2, qTouching, tolerance );
03019     bool rResult = FindIntersectionLineSegmentLineSegment( r, circleCenter, p, q, t1, t2, rTouching, tolerance );
03020     //--------------------------------------------------------------------
03021     // Check Touchings first followed by Results
03022     if ( pTouching || qTouching || pTouching ) {
03023         //std::cout << "Touching: ";
03024         //std::cout << pTouching << "\t" << qTouching << "\t" << rTouching << "\n";
03025         return 11;
03026     }
03027     if ( pResult || qResult || rResult ) {
03028         //std::cout << "Not Touching: ";
03029         //std::cout << pResult << "\t" << qResult << "\t" << rResult << "\n";
03030         return 0;
03031     }
03032     //--------------------------------------------------------------------
03033     T lengthPtoQ = ( p - q ).Length();
03034     T lengthPtoR = ( p - r ).Length();
03035     T lengthQtoR = ( q - r ).Length();
03036     T lengthPointToP = (circleCenter - p).Length();
03037     T lengthPointToQ = (circleCenter - q).Length();
03038     T lengthPointToR = (circleCenter - r).Length();
03039     //--------------------------------------------------------------------
03040     if ( lengthPointToP > lengthPtoR && lengthPointToP > lengthPtoQ ) {
03041         return 0;
03042     }
03043     if ( lengthPointToQ > lengthPtoQ && lengthPointToQ > lengthQtoR ) {
03044         return 0;
03045     }
03046     if ( lengthPointToR > lengthPtoR && lengthPointToR > lengthQtoR ) {
03047         return 0;
03048     }
03049     //--------------------------------------------------------------------
03050     return 21;
03051 }
03052 //-----------------------------------------------------------------------------
03053 
03054 //*****************************************************************************
03055 // Find if a Point is in a Triangle
03056 // (Assume the point lies on the triangle plane)
03057 // I/P: a vector defining a point on the triangle plane
03058 // I/P: three vectors defining a triangle in counter-clockwise dir
03059 // O/P: a closest distance (not implemented yet)
03060 // REMARK: This fn is used by FindIntersectionTriangleTriangle fn
03061 //*****************************************************************************
03062 template <typename T>
03063 bool CGMath<T>::FindIfAPointIsInATriangleOnTheSamePlane (
03064         Vector3<T> const & pt,      // a point
03065         Vector3<T> const & p,       // a triangle
03066         Vector3<T> const & q, 
03067         Vector3<T> const & r, 
03068         T tolerance = Math<T>::ThresholdZero
03069 )
03070 {
03071     // Test if the vector formed by the cross product of vector (tri_pt1 - tri_pt0) and (pt - tri_pt0) 
03072     // and the vector formed by the cross product of vector (tri_pt1 - tri_pt0) and (tri_pt2 - tri_pt0) 
03073     // has the same direction.
03074     //
03075     //            * 1
03076     //           / \
03077     //          /   \
03078     //         /     \
03079     //        /   *   \
03080     //       /    pt   \
03081     //      /           \
03082     //   2 * -----------* 0
03083     //
03084     // The test has to be for all the three combinations of the triangle points.
03085     // If all test result in the same direction then the point is in the triangle.
03086     //*
03087     if ( ( ( (q-p)^(pt-p) ) * ( (q-p)^(r-p) ) ) < 0 )   return false;
03088     if ( ( ( (r-q)^(pt-q) ) * ( (r-q)^(p-q) ) ) < 0 )   return false;
03089     if ( ( ( (p-r)^(pt-r) ) * ( (p-r)^(q-r) ) ) < 0 )   return false;
03090     return true;
03091     //*/
03092 
03093     /*
03094 
03095     //                \      /
03096     //                 \    /
03097     //                  \  /
03098     //                   \/
03099     //                   /\r
03100     //                  /  \
03101     // qResult := true /    \  pResult := true if line(p,pt) doesn't intersect line(q,r)
03102     //                / Tri  \
03103     // _____________ /________\_________________
03104     //              /p         \q
03105     //             /            \
03106     //            /              \
03107     //           /                \
03108     //          / rResult := true if line(r,pt) doesn't intersect line(p,q)
03109     //
03110     // qResult := true if line(q,pt) doesn't interscet line(r,p)
03111     //--------------------------------------------------------------------
03112     // Case the point lies on a line of triangle
03113     {
03114         Vector3<T> pq( p-q );
03115         Vector3<T> ptp( (pt-p) );
03116         if ( (ptp^pq).Length() < tolerance ) {
03117             T LEN = pq.Length();
03118             T len1 = ptp.Length();
03119             T len2 = (pt-q).Length();
03120             if ( len1 <= LEN && len2 <= LEN )   return true;
03121             else                                return false;
03122         }
03123     }
03124     {
03125         Vector3<T> qr( q-r );
03126         Vector3<T> ptq( (pt-q) );
03127         if ( (ptq^qr).Length() < tolerance ) {
03128             T LEN = qr.Length();
03129             T len1 = ptq.Length();
03130             T len2 = (pt-r).Length();
03131             if ( len1 <= LEN && len2 <= LEN )   return true;
03132             else                                return false;
03133         }
03134     }
03135     {
03136         Vector3<T> rp( r-p );
03137         Vector3<T> ptr( (pt-r) );
03138         if ( (ptr^rp).Length() < tolerance ) {
03139             T LEN = rp.Length();
03140             T len1 = ptr.Length();
03141             T len2 = (pt-p).Length();
03142             if ( len1 <= LEN && len2 <= LEN )   return true;
03143             else                                return false;
03144         }
03145     }
03146     //--------------------------------------------------------------------
03147     // CASE: the point is inside or outside of the triangle
03148     T t1, t2;
03149     bool pTouching, qTouching, rTouching;
03150     bool pResult = FindIntersectionLineSegmentLineSegment( p, pt, q, r, t1, t2, pTouching, tolerance );
03151     bool qResult = FindIntersectionLineSegmentLineSegment( q, pt, r, p, t1, t2, qTouching, tolerance );
03152     bool rResult = FindIntersectionLineSegmentLineSegment( r, pt, p, q, t1, t2, rTouching, tolerance );
03153     //--------------------------------------------------------------------
03154     // Check Touchings first followed by Results
03155     if ( pTouching || qTouching || pTouching ) {
03156         //std::cout << "Touching: ";
03157         //std::cout << pTouching << "\t" << qTouching << "\t" << rTouching << "\n";
03158         return true;
03159     }
03160     if ( pResult || qResult || rResult ) {
03161         //std::cout << "Not Touching: ";
03162         //std::cout << pResult << "\t" << qResult << "\t" << rResult << "\n";
03163         return false;
03164     }
03165     //--------------------------------------------------------------------
03166     T lengthPtoQ = ( p - q ).Length();
03167     T lengthPtoR = ( p - r ).Length();
03168     T lengthQtoR = ( q - r ).Length();
03169     T lengthPointToP = (pt - p).Length();
03170     T lengthPointToQ = (pt - q).Length();
03171     T lengthPointToR = (pt - r).Length();
03172     //--------------------------------------------------------------------
03173     if ( lengthPointToP > lengthPtoR && lengthPointToP > lengthPtoQ ) {
03174         return false;
03175     }
03176     if ( lengthPointToQ > lengthPtoQ && lengthPointToQ > lengthQtoR ) {
03177         return false;
03178     }
03179     if ( lengthPointToR > lengthPtoR && lengthPointToR > lengthQtoR ) {
03180         return false;
03181     }
03182     //--------------------------------------------------------------------
03183     return true;
03184     //*/
03185 }
03186 //-----------------------------------------------------------------------------
03187 
03188 //*****************************************************************************
03189 // Find the centroid of a Triangle
03190 //*****************************************************************************
03191 template <typename T>
03192 Vector3<T> CGMath<T>::CentroidOfTriangle (
03193         Vector3<T> const & p,       
03194         Vector3<T> const & q,       
03195         Vector3<T> const & r        
03196 )
03197 {
03198     return Vector3<T>( ( p + q + r ) / T(3) );
03199 }
03200 //-----------------------------------------------------------------------------
03201 
03202 //*****************************************************************************
03203 // Find if a Point is in a Triangle
03204 // (No assumption whether the point lies on the triangle plane)
03205 // I/P: a vector defining a point on the triangle plane
03206 // I/P: three vectors defining a triangle in counter-clockwise dir
03207 // O/P: a closest distance (not implemented yet)
03208 // REMARK: This fn is used by FindIntersectionCylinderTriangle fn
03209 //*****************************************************************************
03210 template <typename T>
03211 bool CGMath<T>::FindIfAPointIsInATriangle (
03212         Vector3<T> const & pt,      // a point
03213         Vector3<T> const & p,       // a triangle
03214         Vector3<T> const & q, 
03215         Vector3<T> const & r, 
03216         T tolerance = Math<T>::ThresholdZero
03217 )
03218 {
03219     //                \      /
03220     //                 \    /
03221     //                  \  /
03222     //                   \/
03223     //                   /\r
03224     //                  /  \
03225     // qResult := true /    \  pResult := true
03226     //                / Tri  \
03227     // _____________ /________\_________________
03228     //              /p         \q
03229     //             /            \
03230     //            /              \
03231     //           /                \
03232     //          / rResult := true  \
03233     //
03234     //--------------------------------------------------------------------
03235     // Find the normal of triangle#1
03236     Vector3<T> N = (q - p) ^ (r - p);
03237     N.Normalized();
03238     //--------------------------------------------------------------------
03239     // The point is not on the triangle if it doesn't lie on the triangle plane
03240     T Kplane = p * N;       // Plane Constant
03241     T ptP = N*pt - Kplane;
03242     if ( fabs( ptP ) > tolerance ) return false;
03243 
03244     FindIfAPointIsInATriangleOnTheSamePlane( pt, p, q, r, tolerance );
03245     // The code below were replaced by the above statement!
03246     /*
03247     //--------------------------------------------------------------------
03248     // Case the point lies on a line of triangle
03249     {
03250         Vector3<T> pq( p-q );
03251         Vector3<T> ptp( (pt-p) );
03252         if ( (ptp^pq).Length() < tolerance ) {
03253             T LEN = pq.Length();
03254             T len1 = ptp.Length();
03255             T len2 = (pt-q).Length();
03256             if ( len1 <= LEN && len2 <= LEN )   return true;
03257             else                                return false;
03258         }
03259     }
03260     {
03261         Vector3<T> qr( q-r );
03262         Vector3<T> ptq( (pt-q) );
03263         if ( (ptq^qr).Length() < tolerance ) {
03264             T LEN = qr.Length();
03265             T len1 = ptq.Length();
03266             T len2 = (pt-r).Length();
03267             if ( len1 <= LEN && len2 <= LEN )   return true;
03268             else                                return false;
03269         }
03270     }
03271     {
03272         Vector3<T> rp( r-p );
03273         Vector3<T> ptr( (pt-r) );
03274         if ( (ptr^rp).Length() < tolerance ) {
03275             T LEN = rp.Length();
03276             T len1 = ptr.Length();
03277             T len2 = (pt-p).Length();
03278             if ( len1 <= LEN && len2 <= LEN )   return true;
03279             else                                return false;
03280         }
03281     }
03282     T t1, t2;
03283     //--------------------------------------------------------------------
03284     bool pTouching, qTouching, rTouching;
03285     bool pResult = FindIntersectionLineSegmentLineSegment( p, pt, q, r, t1, t2, pTouching, tolerance );
03286     bool qResult = FindIntersectionLineSegmentLineSegment( q, pt, r, p, t1, t2, qTouching, tolerance );
03287     bool rResult = FindIntersectionLineSegmentLineSegment( r, pt, p, q, t1, t2, rTouching, tolerance );
03288     //--------------------------------------------------------------------
03289     //glPushMatrix();
03290     //  glBegin( GL_LINES );
03291     //      glColor3f( 0.15, 0.25, 0.4 );
03292     //      glVertex3fv( &p.GetDataFloat() );
03293     //      glVertex3fv( &pt.GetDataFloat() );
03294     //      glVertex3fv( &q.GetDataFloat() );
03295     //      glVertex3fv( &pt.GetDataFloat() );
03296     //      glVertex3fv( &r.GetDataFloat() );
03297     //      glVertex3fv( &pt.GetDataFloat() );
03298     //  glEnd();
03299     //glPopMatrix();
03300     //--------------------------------------------------------------------
03301     // Check Touchings first followed by Results
03302     if ( pTouching || qTouching || rTouching )  return true;
03303     if ( pResult || qResult || rResult )        return false;
03304     //--------------------------------------------------------------------
03305     T lengthPtoQ = ( p - q ).Length();
03306     T lengthPtoR = ( p - r ).Length();
03307     T lengthQtoR = ( q - r ).Length();
03308     T lengthPointToP = (pt - p).Length();
03309     T lengthPointToQ = (pt - q).Length();
03310     T lengthPointToR = (pt - r).Length();
03311     //--------------------------------------------------------------------
03312     if ( lengthPointToP > lengthPtoR && lengthPointToP > lengthPtoQ ) {
03313         return false;
03314     }
03315     if ( lengthPointToQ > lengthPtoQ && lengthPointToQ > lengthQtoR ) {
03316         return false;
03317     }
03318     if ( lengthPointToR > lengthPtoR && lengthPointToR > lengthQtoR ) {
03319         return false;
03320     }
03321     //--------------------------------------------------------------------
03322     return true;
03323     //*/
03324 }
03325 //-----------------------------------------------------------------------------
03326 //*****************************************************************************
03327 // Find Line Segment - Triangle Intersection
03328 // I/P: two vectors defining the line segment
03329 // I/P: three vectors defining the triangle in counter-clockwise dir
03330 // O/P: the ratio of the point on the line that intersects the plane
03331 // O/P: the projected point on the line that intersects the plane
03332 // Return true if the line segment intersects the triangle.
03333 // Otherwise, return false.
03334 //*****************************************************************************
03335 template <typename T>
03336 bool CGMath<T>::FindIntersectionLineSegmentTriangle (
03337         Vector3<T> const & p1, Vector3<T> const & p2,   // I/P: a line segment
03338         Vector3<T> const & t1,      // I/P: the triangle
03339         Vector3<T> const & t2, 
03340         Vector3<T> const & t3, 
03341         T &            ratio,       // O/P: the ratio
03342         Vector3<T> &  projPt,       // O/P: the projected point
03343         T tolerance 
03344 )
03345 {
03346     //---------------------------------------------------------------
03347     // Find the normal of the triangle
03348     Vector3<T> N = (t2 - t1) ^ (t3 - t1);
03349     N.Normalized();
03350     //---------------------------------------------------------------
03351     // Find the point on the line segment that intersects the plane
03352     FindRatioOfPointOnLineThatIntersectPlane( 
03353         p1, p2, t1, N, ratio, projPt, tolerance );
03354     if ( ratio < 0.0 || 1.0 < ratio )   return false;
03355     //---------------------------------------------------------------
03356     // Find whether the projected point intersects the triangle
03357     return FindIfAPointIsInATriangleOnTheSamePlane( 
03358                 projPt, t1, t2, t3, tolerance );
03359     //---------------------------------------------------------------
03360 }
03361 //-----------------------------------------------------------------------------
03362 //*****************************************************************************
03363 // Find Line Segment - Triangle Intersection
03364 // I/P: two vectors defining the line segment
03365 // I/P: three vectors defining the triangle in counter-clockwise dir
03366 // O/P: the ratio of the point on the line that intersects the plane
03367 // O/P: the projected point on the line that intersects the plane
03368 // O/P: the intersection angle (in degrees) of the line with the plane's normal
03369 // Return true if the line segment intersects the triangle.
03370 // Otherwise, return false.
03371 //*****************************************************************************
03372 template <typename T>
03373 bool CGMath<T>::FindIntersectionLineSegmentTriangle (
03374         Vector3<T> const & p1, Vector3<T> const & p2,   // I/P: a line segment
03375         Vector3<T> const & t1,      // I/P: the triangle
03376         Vector3<T> const & t2, 
03377         Vector3<T> const & t3, 
03378         T &           ratio,                // O/P: the ratio
03379         T &           intersectionAngle,    // O/P: the intersection angle (in degrees) of the line with the plane's normal
03380         Vector3<T> &  projPt,               // O/P: the projected point
03381         T tolerance 
03382 )
03383 {
03384     //---------------------------------------------------------------
03385     // Find the normal of the triangle
03386     Vector3<T> N = (t2 - t1) ^ (t3 - t1);
03387     N.Normalized();
03388     //---------------------------------------------------------------
03389     // Find the point on the line segment that intersects the plane
03390     FindRatioOfPointOnLineThatIntersectPlane( 
03391         p1, p2, t1, N, ratio, projPt, tolerance );
03392     if ( ratio < 0.0 || 1.0 < ratio )   return false;
03393 
03394     intersectionAngle = acos( N * (p2-p1).Normalized() ) * Math<T>::RAD_TO_DEG;
03395     //---------------------------------------------------------------
03396     // Find whether the projected point intersects the triangle
03397     return FindIfAPointIsInATriangleOnTheSamePlane( 
03398                 projPt, t1, t2, t3, tolerance );
03399     //---------------------------------------------------------------
03400 }
03401 //-----------------------------------------------------------------------------
03402 //=============================================================================
03403 
03404 //=============================================================================
03405 // Spline Fns
03406 //=============================================================================
03407 //*****************************************************************************
03408 // CatmullRomSplineSegment Fn
03409 // --------------------------
03410 // I/P: 4 points p0, p1, p2, p3 and t in ranges [0,1]
03411 // O/P: Catmull-Rom Spline Curve Pt 
03412 //*****************************************************************************
03413 //-----------------------------------------------------------------------------
03414 template <typename T>
03415 Vector3<T> CGMath<T>::CatmullRomSplinePt ( 
03416             Vector3<T> const & p0, Vector3<T> const & p1, 
03417             Vector3<T> const & p2, Vector3<T> const & p3, 
03418             T t
03419 )
03420 {
03421     return Vector3<T>( 0.5 * ( 
03422                 (2*p1) +
03423                 (-p0 + p2) * t +
03424                 (2*p0 - 5*p1 + 4*p2 - p3) * t*t +
03425                 (-p0 + 3*p1 - 3*p2 + p3 ) * t*t*t ) );
03426 }
03427 //-----------------------------------------------------------------------------
03428 //=============================================================================
03429 
03430 //=============================================================================
03431 // Subdivision Fns
03432 //=============================================================================
03433 //*****************************************************************************
03434 // SubdivideUniPolyInBBForm Fn (using de Casteljau algorithm)
03435 // ---------------------------
03436     // I/P: P control points and degree
03437     //      # of points is degree + 1
03438     // I/P: t is parameter value in range [0-1]
03439     // O/P: left and right subdivision, each with degree + 1 points
03440     //      with the last point of the left subdivision is the same as 
03441     //      the first pt of the right subdivision
03442 //*****************************************************************************
03443 //-----------------------------------------------------------------------------
03444 template <typename T>
03445 void CGMath<T>::SubdivideUniPolyInBBForm (
03446                     Vector3<T> const P[],   // I/P: points on curve
03447                     int degree,             // I/P: degree
03448                     T   t,                  // I/P: parameter value
03449                     Vector3<T> L[],         // O/P: subdivision points
03450                     Vector3<T> R[]          // O/P: subdivision points
03451 )
03452 {
03453     L[0] = P[0];
03454     R[degree] = P[degree];
03455     Vector3<T> * Q = new Vector3<T>[degree];    // temporary storage
03456     for ( int i = 0; i < degree; ++i ) {
03457         Q[i] = (1-t)*P[i] + t*P[i+1];
03458     }
03459     L[1] = Q[0];
03460     int d = degree - 1;
03461     R[d] = Q[d];
03462     for ( ; d > 0; --d ) {
03463         for ( int i = 0; i < d; ++i ) {
03464             Q[i] = (1-t)*Q[i] + t*Q[i+1];
03465         }
03466         L[degree-d+1] = Q[0];
03467         R[d] = Q[d];
03468     }
03469     R[0] = Q[0];
03470     delete [] Q;
03471 }
03472 //-----------------------------------------------------------------------------
03473 //=============================================================================
03474 
03475 //=============================================================================
03476 // Constraint Fns
03477 //=============================================================================
03478 //*****************************************************************************
03479 // SolveAForConstCubicBezierCurveLength Fn
03480 // ---------------------------------------
03481 // Find unknown A that make the cubic Bezier curve defined by 4 ctrl pts 
03482 // have the curve length equals to the LENGTH contraint with number of 
03483 // subdivision constraint (number of subdivision)
03484 //*****************************************************************************
03485 //-----------------------------------------------------------------------------
03486 template <typename T>
03487 T CGMath<T>::SolveAForConstCubicBezierCurveLength ( 
03488                 const Vector3<T> p0,    // I/P: ctrl pt #1
03489                 const Vector3<T> p3,    // I/P: ctrl pt #4
03490                 const Vector3<T> t0,    // I/P: tangent at pt #1
03491                 const Vector3<T> t3,    // I/P: tangent at pt #4
03492                 int   iNumSubdivision,  // I/P: #subdivision constraint
03493                 T     tLength,          // I/P: length constraint
03494                 T     tolerance,        // I/P: tolerance
03495                 Vector3<T> * pPtOnCurve // O/P: ptr to points on curve
03496 )
03497 {
03498     if ( (p0 - p3).Length() >= tLength ) return 0;
03499     //---------------------------------------------------------------
03500     // Subdivide Bezier curve "iNumSubdivision" times
03501     int iT = static_cast<int>( pow( 2, iNumSubdivision ) );
03502     int iTotalPts = 4*iT - iT + 1;
03503     //std::cout << "iTotalPts: " << iTotalPts << "\n";
03504     Vector3<T> * P = new Vector3<T>[iTotalPts];
03505     Vector3<T> * Q = new Vector3<T>[iTotalPts];
03506     Vector3<T> * R; // = new Vector3<T>[iTotalPts];
03507     //---------------------------------------------------------------
03508     T tUpper = 1000;    // upper range limit
03509     T tLower = 0;       // lower range limit
03510     T A = (tUpper + tLower) / static_cast<T>( 2.0 );
03511     T tError;
03512     T tCurveLength = 0;
03513     P[0] = p0;
03514     //---------------------------------------------------------------
03515     // Constraint the curve length
03516     //---------------------------------------------------------------
03517     while ( true ) {
03518         P[1] = p0 + A*t0;
03519         P[2] = p3 + A*t3;
03520         P[3] = p3;
03521         //----------------------------------------------------------------
03522         for ( int i = 0; i < iNumSubdivision; ++i ) {
03523             for ( int c = 0; c < pow(2,i)*3; c+=3 ) {
03524                 SubdivideUniPolyInBBForm( &P[c], 3, 0.5, &Q[c*2], &Q[c*2+3] );
03525             }
03526             // Swap
03527             R = P;
03528             P = Q;
03529             Q = R;
03530         }
03531         //----------------------------------------------------------------
03532         tCurveLength = 0;
03533         for ( int i = 1; i < iTotalPts; ++i ) {
03534             tCurveLength += ( P[i] - P[i-1] ).Length();
03535         }
03536         //----------------------------------------------------------------
03537         //std::cout << "CurveLength = " << tCurveLength << "\n";
03538         tError = tCurveLength - tLength;
03539         if      ( tError > tolerance ) {
03540             tUpper = A;
03541             A = static_cast<T>( (tUpper + tLower) / 2.0 );
03542         }
03543         else if ( tError < -tolerance ) {
03544             tLower = A;
03545             A = static_cast<T>( (tUpper + tLower) / 2.0 );
03546         }
03547         else {
03548             if ( pPtOnCurve ) {
03549                 for ( int i = 0; i < iTotalPts; ++i ) {
03550                     pPtOnCurve[i] = P[i];
03551                 }
03552             }
03553             delete [] P;
03554             delete [] Q;
03555             //std::cout << "tCurveLength: " << tCurveLength << std::endl;
03556             return A;
03557         }
03558         //std::cout << "upper: " << tUpper 
03559         //  << "  A: " << A 
03560         //  << "  lower: " << tLower
03561         //  << "\n";
03562         /*
03563         if ( A == 0 ) {
03564             delete [] P;
03565             delete [] Q;
03566             return A;
03567         }
03568         //*/
03569     }
03570     //---------------------------------------------------------------
03571     //return A;
03572 }
03573 //-----------------------------------------------------------------------------
03574 //=============================================================================
03575 
03576 //=============================================================================
03577 // Constraint Fns
03578 //=============================================================================
03579 //*****************************************************************************
03580 // TransformALinkToWorldCoordinates Fn
03581 // -----------------------------------
03582 // vector v = p1 - p0 will be transfromed to align with x-axis of the world 
03583 // coordinates.
03584 // O/P: theta and phi angles for z-rotation and x'-rotation respectively
03585 //*****************************************************************************
03586 //-----------------------------------------------------------------------------
03587 template <typename T>
03588 Vector3<T> CGMath<T>::TransformALinkToWorldXAxis ( 
03589                 const Vector3<T> V, // I/P: V
03590                 T & Cy,             // O/P: cosine(theta) of y-rotation
03591                 T & Sy,             // O/P: sine(theta) of y-rotation
03592                 T & Cz,             // O/P: cosine(phi) of z-rotation
03593                 T & Sz              // O/P: sine(phi) of z-rotation
03594                 // return   Rz * Ry * V;
03595                 // where Rz = [  Cz -Sz  0  ]
03596                 //            [  Sz  Cz  0  ]
03597                 //            [  0   0   1  ]
03598                 // and   Ry = [  Cy  0   Sy ]
03599                 //            [  0   1   0  ]
03600                 //            [ -Sy  0   Cy ]
03601 )
03602 {
03603     //===============================================================
03604     // RECORD angles in Cy, Sy, Cz, and Sz
03605     // since it takes care of all quadrants by keeping them separately
03606     // instead of keeping just theta and phi angles
03607     //---------------------------------------------------------------
03608 
03609     //===============================================================
03610     // Variables
03611     //---------------------------------------------------------------
03612     //Real c, s;
03613     Real D;
03614     Matrix3x3<Real> Ry, Rz;
03615     Vector3<T> OP = V;
03616     //===============================================================
03617     // ROTATE r to x-axis
03618     //---------------------------------------------------------------
03619     // Rotate OP to xy-plane
03620     D = sqrt( OP[0]*OP[0] + OP[2]*OP[2] );
03621     if ( D > 0 ) {
03622         Cy = OP[0] / D;
03623         Sy = OP[2] / D;
03624     }
03625     else {
03626         std::cout << "ERROR: D length is zero!\n";
03627         exit(-1);
03628     }
03629     Ry = Matrix3x3<Real>(
03630              Cy,  0,  Sy,
03631              0,   1,  0,
03632             -Sy,  0,  Cy
03633     );
03634     OP = Ry * OP;
03635     // Rotate it again to x-axis
03636     D = sqrt( OP[0]*OP[0] + OP[1]*OP[1] );
03637     if ( D > 0 ) {
03638         Cz =  OP[0] / D;
03639         Sz = -OP[1] / D;
03640     }
03641     else {
03642         std::cout << "ERROR: D length is zero!\n";
03643         exit(-1);
03644     }
03645     Rz = Matrix3x3<Real>(
03646             Cz, -Sz, 0,
03647             Sz,  Cz, 0,
03648             0,   0,  1
03649     );
03650     OP = Rz * OP;
03651     //*
03652     std::cout << "V: " << V << " with length of " << V.Length() << "\n";
03653     std::cout << "OP: " << OP << "\n";
03654     //*/
03655     //---------------------------------------------------------------
03656     return OP;
03657 }
03658 //-----------------------------------------------------------------------------
03659 
03660 
03661 
03662 
03663 //=============================================================================
03664 // Helper Function for Collision Detection and Response
03665 //-----------------------------------------------------------------------------
03666 template <typename T>
03667 bool CGMath<T>::CD_SphereAtOrigin_vs_Point (
03668         T   sphere_radius,                  
03669         Vector3<T> const & point,           
03670         Vector3<T> & shortestDistanceOut    
03671 )
03672 {
03673     //---------------------------------------------------------------
03674     // The sphere has a radius and centers at the origin
03675     T   ptRadius = point.Length();
03676     //-----------------------------------------------------
03677     // If the point is within the sphere radius
03678     if ( ptRadius <= sphere_radius ) {
03679 
03680         // Find the shortest distance from the point to the sphere surface
03681         T difRadius = sphere_radius - ptRadius;
03682         // If the point is at the origin (degenerate case)
03683         if ( difRadius >= sphere_radius ) {
03684             shortestDistanceOut.SetXYZ( 0, sphere_radius, 0 );
03685         }
03686         else {
03687             shortestDistanceOut = point.GetUnit() * difRadius;
03688         }
03689 
03690         return true;
03691     }
03692     //---------------------------------------------------------------
03693     return false;
03694 }
03695 // END: TEST_SphereAtOrigin_vs_Point(...)
03696 //-----------------------------------------------------------------------------
03697 
03698 
03699 //-----------------------------------------------------------------------------
03700 template <typename T>
03701 bool CGMath<T>::CD_CylinderAtOrigin_vs_Point (
03702         T   cylinder_radius,                
03703         T   cylinder_height,                
03704         Vector3<T> const & point,           
03705         Vector3<T> & shortestDistanceOut    
03706 )
03707 {
03708     //---------------------------------------------------------------
03709     // In the local coordinate of the bounding cylinder, 
03710     // the cylinder axis is parallel to z-axis 
03711     // where it is centered at the origin.
03712     // The cylinder has radius and height.
03713     // Its height is measured from -z and +z axis
03714     // Its center is situated between height/2 in -z and +z axis.
03715     T   halfHeight = cylinder_height / T(2.0);
03716     //-----------------------------------------------------
03717     // If the point is within the cylinder height
03718     if ( -halfHeight <= point[2] && point[2] <= halfHeight ) {
03719         // If the point is within the cylinder radius
03720         T   ptRadius = sqrt( point[0]*point[0] + point[1]*point[1] );
03721         T difRadius = cylinder_radius - ptRadius;
03722         if ( difRadius >= 0 ) {
03723             // Find the shortest distance from the point to the cylinder surface
03724             T difHeight = halfHeight - fabs( point[2] );
03725             if ( difRadius <= difHeight ) {
03726                 // If the point is on the z-axis (degenerate case)
03727                 // I.e., point[0] and point[1] are zeroes (same as ptRadius == cylinder_radius)
03728                 if ( ptRadius == cylinder_radius ) {
03729                     shortestDistanceOut.SetXYZ( 0, cylinder_radius, 0 );
03730                 }
03731                 // If the point is NOT on the z-axis
03732                 else {
03733                     Vector2<T> difDirection = Vector2<T>( point[0], point[1] );
03734                     difDirection.Normalized();
03735                     difDirection *= difRadius;
03736                     shortestDistanceOut.SetXYZ( difDirection[0], difDirection[1], 0 );
03737                 }
03738             }
03739             else {
03740                 shortestDistanceOut.SetXYZ( 0, 0, point[2] >= 0 ? difHeight : -difHeight );
03741             }
03742 
03743             return true;
03744         }
03745     }
03746     //---------------------------------------------------------------
03747     return false;
03748 }
03749 // END: TEST_CylinderAtOrigin_vs_Point(...)
03750 //-----------------------------------------------------------------------------
03751 
03752 
03753 //-----------------------------------------------------------------------------
03754 template <typename T>
03755 bool CGMath<T>::CD_CylinderAtOrigin_vs_Sphere (
03756         T   cylinder_radius,                
03757         T   cylinder_height,                
03758         Vector3<T> const & sphereCenter,    
03759         T                  sphereRadius     
03760 )
03761 {
03762     //---------------------------------------------------------------
03763     // In the local coordinate of the bounding cylinder, 
03764     // the cylinder axis is parallel to z-axis 
03765     // where it is centered at the origin.
03766     // The cylinder has radius and height.
03767     // Its height is measured from -z and +z axis
03768     // Its center is situated between height/2 in -z and +z axis.
03769     T   halfHeight = cylinder_height / T(2.0);
03770     //-----------------------------------------------------
03771     // If the point is within the cylinder height
03772     if ( -halfHeight <= sphereCenter[2] && sphereCenter[2] <= halfHeight ) {
03773         // If the point is within the cylinder radius
03774         T   ptRadius = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03775         T difRadius = cylinder_radius + sphereRadius - ptRadius;
03776         if ( difRadius >= 0 ) {
03777             return true;
03778         }
03779     }
03780     // If the point is NOT within the cylinder height
03781     else {
03782         // If the sphere center is within (halfHeight + sphereRadius)
03783         //
03784         //      sphere center o---------*--+ sphere boundary
03785         //                    |         |
03786         //                    |         h
03787         //                    |         |
03788         //                    |<--len-->*-----.-----*  top of cylinder
03789         //                    +         |           |
03790         //                              |           |
03791         //                    |<--proj_len--->|     |
03792         //                              |           |
03793         //
03794         //    len = sqrt( sphere_radius - h^2 )
03795         //    proj_len = sqrt( sphere_center[0]^2 + sphere_center[1]^2 )
03796         //
03797         //    If len is greater than or equal to ( proj_len - cylinder_radius ), 
03798         //    the sphere intersects or touches the cylinder.
03799         //
03800         if ( halfHeight < sphereCenter[2] && sphereCenter[2] <= halfHeight + sphereRadius ) {           // Top
03801             T height = sphereCenter[2] - halfHeight;
03802             T ls = sphereRadius*sphereRadius - height*height;
03803             if ( ls < 0 )   return false;   // the height is too far
03804             T len = sqrt( ls );
03805             T proj_len = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03806             T dif = len - ( proj_len - cylinder_radius );
03807             if ( dif >= 0 ) {
03808                 return true;
03809             }
03810         }
03811         else if ( -halfHeight > sphereCenter[2] && sphereCenter[2] >= -halfHeight - sphereRadius ) {        // Bottom
03812             T height = -sphereCenter[2] - halfHeight;
03813             T ls = sphereRadius*sphereRadius - height*height;
03814             if ( ls < 0 )   return false;   // the height is too far
03815             T len = sqrt( ls );
03816             T proj_len = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03817             T dif = len - ( proj_len - cylinder_radius );
03818             if ( dif >= 0 ) {
03819                 return true;
03820             }
03821         }
03822     }
03823     //---------------------------------------------------------------
03824     return false;
03825 }
03826 // END: TEST_CylinderAtOrigin_vs_Sphere(...)
03827 //-----------------------------------------------------------------------------
03828 
03829     
03830 //-----------------------------------------------------------------------------
03831 template <typename T>
03832 bool CGMath<T>::CD_CylinderAtOrigin_vs_Sphere (
03833         T   cylinder_radius,                
03834         T   cylinder_height,                
03835         Vector3<T> const & sphereCenter,    
03836         T                  sphereRadius,    
03837         Vector3<T> & shortestDistanceOut    
03838 )
03839 {
03840     //---------------------------------------------------------------
03841     // In the local coordinate of the bounding cylinder, 
03842     // the cylinder axis is parallel to z-axis 
03843     // where it is centered at the origin.
03844     // The cylinder has radius and height.
03845     // Its height is measured from -z and +z axis
03846     // Its center is situated between height/2 in -z and +z axis.
03847     T   halfHeight = cylinder_height / 2.0;
03848     //-----------------------------------------------------
03849     // If the point is within the cylinder height
03850     if ( -halfHeight <= sphereCenter[2] && sphereCenter[2] <= halfHeight ) {
03851         // If the point is within the cylinder radius
03852         T   ptRadius = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03853         T difRadius = cylinder_radius + sphereRadius - ptRadius;
03854         if ( difRadius >= 0 ) {
03855 
03856             // Find the shortest distance from the point to the cylinder surface
03857             T difHeight = halfHeight - fabs( sphereCenter[2] );
03858             // If the sphere center is outside the cylinder
03859             if ( difRadius - sphereRadius <= difHeight ) {
03860                 // If the point is on the z-axis (degenerate case)
03861                 // I.e., point[0] and point[1] are zeroes (same as ptRadius == cylinder_radius)
03862                 if ( ptRadius == cylinder_radius ) {
03863                     shortestDistanceOut.SetXYZ( 0, cylinder_radius, 0 );
03864                 }
03865                 // If the point is NOT on the z-axis
03866                 else {
03867                     Vector2<T> difDirection = Vector2<T>( sphereCenter[0], sphereCenter[1] );
03868                     difDirection.Normalized();
03869                     difDirection *= difRadius;
03870                     shortestDistanceOut.SetXYZ( difDirection[0], difDirection[1], 0 );
03871                 }
03872             }
03873             else {
03874                 shortestDistanceOut.SetXYZ( 0, 0, sphereCenter[2] >= 0 ? difHeight : -difHeight );
03875             }
03876 
03877             return true;
03878         }
03879     }
03880     // If the point is NOT within the cylinder height
03881     else {
03882         // If the sphere center is within (halfHeight + sphereRadius)
03883         //
03884         //      sphere center o---------*--+ sphere boundary
03885         //                    |         |
03886         //                    |         h
03887         //                    |         |
03888         //                    |<--len-->*-----.-----*  top of cylinder
03889         //                    +         |           |
03890         //                              |           |
03891         //                    |<--proj_len--->|     |
03892         //                              |           |
03893         //
03894         //    len = sqrt( sphere_radius - h^2 )
03895         //    proj_len = sqrt( sphere_center[0]^2 + sphere_center[1]^2 )
03896         //
03897         //    If len is greater than or equal to ( proj_len - cylinder_radius ), 
03898         //    the sphere intersects or touches the cylinder.
03899         //
03900         if ( halfHeight < sphereCenter[2] && sphereCenter[2] <= halfHeight + sphereRadius ) {           // Top
03901             T height = sphereCenter[2] - halfHeight;
03902             T ls = sphereRadius*sphereRadius - height*height;
03903             if ( ls < 0 )   return false;   // the height is too far
03904             T len = sqrt( ls );
03905             T proj_len = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03906             T dif = len - ( proj_len - cylinder_radius );
03907             if ( dif >= 0 ) {
03908 
03909                 // Find the shortest length
03910                 Vector2<T> difDirection = Vector2<T>( sphereCenter[0], sphereCenter[1] );
03911                 difDirection.Normalized();
03912                 difDirection *= dif;
03913                 shortestDistanceOut.SetXYZ( difDirection[0], difDirection[1], 0 );
03914 
03915                 return true;
03916             }
03917         }
03918         else if ( -halfHeight > sphereCenter[2] && sphereCenter[2] >= -halfHeight - sphereRadius ) {        // Bottom
03919             T height = -sphereCenter[2] - halfHeight;
03920             T ls = sphereRadius*sphereRadius - height*height;
03921             if ( ls < 0 )   return false;   // the height is too far
03922             T len = sqrt( ls );
03923             T proj_len = sqrt( sphereCenter[0]*sphereCenter[0] + sphereCenter[1]*sphereCenter[1] );
03924             T dif = len - ( proj_len - cylinder_radius );
03925             if ( dif >= 0 ) {
03926 
03927                 // Find the shortest length
03928                 Vector2<T> difDirection = Vector2<T>( sphereCenter[0], sphereCenter[1] );
03929                 difDirection.Normalized();
03930                 difDirection *= dif;
03931                 shortestDistanceOut.SetXYZ( difDirection[0], difDirection[1], 0 );
03932 
03933                 return true;
03934             }
03935         }
03936     }
03937     //---------------------------------------------------------------
03938     return false;
03939 }
03940 // END: TEST_CylinderAtOrigin_vs_Sphere(...)
03941 //-----------------------------------------------------------------------------
03942 // Helper Function for Collision Detection and Response
03943 //=============================================================================
03944 
03945 
03946 
03947 
03948 //=============================================================================
03949 // Sphere-Sphere Intersection Test
03950 //-----------------------------------------------------------------------------
03951 template <typename T>
03952 T CGMath<T>::IntersectionDistance_Sphere_vs_Sphere (
03953         Vector3<T> const & centerA,         
03954         T radiusA,                          
03955         Vector3<T> const & centerB,         
03956         T radiusB,                          
03957         Vector3<T> & shortestDistanceOut    
03958 )
03959 {
03960     // Use centerB - centerA, so that shortestDistanceOut *= length; can be used 
03961     // instead of shortestDistanceOut *= -length;
03962     shortestDistanceOut = centerB - centerA;
03963     T length = shortestDistanceOut.Length() - ( radiusA + radiusB );
03964     shortestDistanceOut.Normalized();
03965     shortestDistanceOut *= length;
03966     return length;
03967 }
03968 //-----------------------------------------------------------------------------
03969 template <typename T>
03970 T CGMath<T>::IntersectionDistance_Sphere_vs_Sphere (
03971         Vector3<T> const & centerA,         
03972         T radiusA,                          
03973         Vector3<T> const & centerB,         
03974         T radiusB,                          
03975         Matrix4x4<T> const & transformB,    
03976         Vector3<T> & shortestDistanceOut    
03977 )
03978 {
03979     // Use centerB - centerA, so that shortestDistanceOut *= length; can be used 
03980     // instead of shortestDistanceOut *= -length;
03981     shortestDistanceOut = transformB * Vector4<T>(centerB).GetVector3() - centerA;
03982     T length = shortestDistanceOut.Length() - ( radiusA + radiusB );
03983     shortestDistanceOut.Normalized();
03984     shortestDistanceOut *= length;
03985     return length;
03986 }
03987 //-----------------------------------------------------------------------------
03988 template <typename T>
03989 T CGMath<T>::IntersectionDistance_Sphere_vs_Sphere (
03990         Vector3<T> const & centerA,         
03991         T radiusA,                          
03992         Matrix4x4<T> const & transformA,    
03993         Vector3<T> const & centerB,         
03994         T radiusB,                          
03995         Vector3<T> & shortestDistanceOut    
03996 )
03997 {
03998     // Use centerB - centerA, so that shortestDistanceOut *= length; can be used 
03999     // instead of shortestDistanceOut *= -length;
04000     shortestDistanceOut = centerB - transformA * Vector4<T>(centerA).GetVector3();
04001     T length = shortestDistanceOut.Length() - ( radiusA + radiusB );
04002     shortestDistanceOut.Normalized();
04003     shortestDistanceOut *= length;
04004     return length;
04005 }
04006 //-----------------------------------------------------------------------------
04007 template <typename T>
04008 T CGMath<T>::IntersectionDistance_Sphere_vs_Sphere (
04009         Vector3<T> const & centerA,         
04010         T radiusA,                          
04011         Matrix4x4<T> const & transformA,    
04012         Vector3<T> const & centerB,         
04013         T radiusB,                          
04014         Matrix4x4<T> const & transformB,    
04015         Vector3<T> & shortestDistanceOut    
04016 )
04017 {
04018     // Use centerB - centerA, so that shortestDistanceOut *= length; can be used 
04019     // instead of shortestDistanceOut *= -length;
04020     shortestDistanceOut = transformB * Vector4<T>(centerB).GetVector3() - transformA * Vector4<T>(centerA).GetVector3();
04021     T length = shortestDistanceOut.Length() - ( radiusA + radiusB );
04022     shortestDistanceOut.Normalized();
04023     shortestDistanceOut *= length;
04024     return length;
04025 }
04026 //-----------------------------------------------------------------------------
04027 // Sphere-Sphere Intersection Test
04028 //=============================================================================
04029 
04030 
04031 
04032 
04033 //=============================================================================
04034 // Interpolation Functions
04035 //-----------------------------------------------------------------------------
04036 template <typename T>
04037 T CGMath<T>::LinearInterpolation (
04038         T val1,     
04039         T val2,     
04040         T percent   
04041 )
04042 {
04043     return  val1 + percent*(val2-val1);
04044 }
04045 //-----------------------------------------------------------------------------
04046 template <typename T>
04047 Vector2<T> CGMath<T>::LinearInterpolation (
04048         Vector2<T> val1,    
04049         Vector2<T> val2,    
04050         T percent           
04051 )
04052 {
04053     return  Vector2<T>( 
04054         val1[0] + percent*(val2[0]-val1[0]), 
04055         val1[1] + percent*(val2[1]-val1[1]) 
04056     );
04057 }
04058 //-----------------------------------------------------------------------------
04059 template <typename T>
04060 Vector3<T> CGMath<T>::LinearInterpolation (
04061         Vector3<T> val1,    
04062         Vector3<T> val2,    
04063         T percent           
04064 )
04065 {
04066     return  Vector3<T>( 
04067         val1[0] + percent*(val2[0]-val1[0]), 
04068         val1[1] + percent*(val2[1]-val1[1]), 
04069         val1[2] + percent*(val2[2]-val1[2]) 
04070     );
04071 }
04072 //-----------------------------------------------------------------------------
04073 template <typename T>
04074 Vector4<T> CGMath<T>::LinearInterpolation (
04075         Vector4<T> val1,    
04076         Vector4<T> val2,    
04077         T percent           
04078 )
04079 {
04080     return  Vector4<T>( 
04081         val1[0] + percent*(val2[0]-val1[0]), 
04082         val1[1] + percent*(val2[1]-val1[1]), 
04083         val1[2] + percent*(val2[2]-val1[2]), 
04084         val1[3] + percent*(val2[3]-val1[3]) 
04085     );
04086 }
04087 //-----------------------------------------------------------------------------
04088 // Interpolation Functions
04089 //=============================================================================
04090 
04091 
04092 
04093 
04094 //=============================================================================
04095 END_NAMESPACE_TAPs
04096 //34567890123456789012345678901234567890123456789012345678901234567890123456789
04097 //--+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines