![]() |
TAPs 0.7.7.3
|
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----+----