00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #ifndef CMathsH
00023 #define CMathsH
00024
00025 #include "math/CMatrix3d.h"
00026 #include <math.h>
00027
00028
00029
00038
00039
00040
00047
00048 inline bool cZero(const double& a_value)
00049 {
00050 return ((a_value < CHAI_TINY) && (a_value > -CHAI_TINY));
00051 }
00052
00053
00054
00065
00066 inline bool cPositiveBound(const double& a_value, const double& a_boundMax)
00067 {
00068 return ((a_value > CHAI_TINY) && ((a_boundMax < 0) || (a_value < a_boundMax)));
00069 }
00070
00071
00072
00079
00080 template<class T> inline T cAbs(const T a_value)
00081 {
00082 return (a_value >= 0 ? a_value : -a_value);
00083 }
00084
00085
00086
00097
00098 template<class T> inline T cMax(const T a_value1, const T a_value2)
00099 {
00100 return (a_value1 >= a_value2 ? a_value1 : a_value2);
00101 }
00102
00103
00104
00115
00116 template<class T> inline T cMin(const T a_value1, const T a_value2)
00117 {
00118 return (a_value1 <= a_value2 ? a_value1 : a_value2);
00119 }
00120
00121
00122
00131
00132 template<class T> inline T cMax3(const T& a_value1, const T& a_value2, const T& a_value3)
00133 {
00134 return (cMax(a_value1, cMax(a_value2, a_value3)));
00135 }
00136
00137
00138
00147
00148 template<class T> inline T cMin3(const T& a_value1, const T& a_value2, const T& a_value3)
00149 {
00150 return (cMin(a_value1, cMin(a_value2, a_value3)));
00151 }
00152
00153
00154
00165
00166 template<class T> inline T cMaxAbs(const T a_value1, const T a_value2)
00167 {
00168 return (cAbs(a_value1) >= cAbs(a_value2) ? a_value1 : a_value2);
00169 }
00170
00171
00172
00183
00184 template<class T> inline T cMinAbs(const T a_value1, const T a_value2)
00185 {
00186 return (cAbs(a_value1) <= cAbs(a_value2) ? a_value1 : a_value2);
00187 }
00188
00189
00190
00199
00200 template<class T> inline T cMax3Abs(const T& a_value1, const T& a_value2, const T& a_value3)
00201 {
00202 return cMaxAbs(a_value1, cMaxAbs(a_value2, a_value3));
00203 }
00204
00205
00206
00215
00216 template<class T> inline T cMin3Abs(const T& a_value1, const T& a_value2, const T& a_value3)
00217 {
00218 return cMinAbs(a_value1, cMinAbs(a_value2, a_value3));
00219 }
00220
00221
00222
00229
00230 template<class T> inline void cSwap(T &a_value1, T &a_value2)
00231 {
00232 T value = a_value1;
00233 a_value1 = a_value2;
00234 a_value2 = value;
00235 }
00236
00237
00238
00247
00248 template<class T> inline T cLerp(const double& a_level, const T& a_value1, const T& a_value2)
00249 {
00250 return (a_value2 * a_level + a_value1 * (1 - a_level));
00251 }
00252
00253
00254
00266
00267 template<class T> inline T cClamp(const T a_value, const T a_low, const T a_high)
00268 {
00269 return (a_value < a_low ? a_low : a_value > a_high ? a_high : a_value);
00270 }
00271
00272
00273
00280
00281 template<class T> inline T cClamp0(T& a_value)
00282 {
00283 return cMax<T>(0, a_value);
00284 }
00285
00286
00287
00294
00295 inline double cClamp01(double& a_value)
00296 {
00297 return (cClamp(a_value, 0.0, 1.0));
00298 }
00299
00300
00301
00311
00312 template<class T, class V> inline bool cContains(const T& a_value, const V& a_low, const V& a_high)
00313 {
00314 return ((a_value >= a_low) && (a_value <= a_high));
00315 }
00316
00317
00318
00325
00326 inline double cSqr(const double& a_value)
00327 {
00328 return(a_value*a_value);
00329 }
00330
00331
00332
00339
00340 inline double cCosDeg(const double& a_angleDeg)
00341 {
00342 return (cos(a_angleDeg * CHAI_DEG2RAD));
00343 }
00344
00345
00346
00353
00354 inline double cSinDeg(const double& a_angleDeg)
00355 {
00356 return (sin(a_angleDeg * CHAI_DEG2RAD));
00357 }
00358
00359
00360
00367
00368 inline double cTanDeg(const double& a_angleDeg)
00369 {
00370 return (tan(a_angleDeg * CHAI_DEG2RAD));
00371 }
00372
00373
00374
00381
00382 inline double cCosRad(const double& a_angleRad)
00383 {
00384 return (cos(a_angleRad));
00385 }
00386
00387
00388
00395
00396 inline double cSinRad(const double& a_value)
00397 {
00398 return (sin(a_value));
00399 }
00400
00401
00402
00409
00410 inline double cTanRad(const double& a_value)
00411 {
00412 return (tan(a_value));
00413 }
00414
00415
00416
00423
00424 inline double cDegToRad(const double& a_angleDeg)
00425 {
00426 return (a_angleDeg * CHAI_DEG2RAD);
00427 }
00428
00429
00430
00437
00438 inline double cRadToDeg(const double& a_angleRad)
00439 {
00440 return (a_angleRad * CHAI_RAD2DEG);
00441 }
00442
00443
00444
00453
00454 inline cVector3d cAdd(const cVector3d& a_vector1, const cVector3d& a_vector2)
00455 {
00456 return cVector3d(
00457 a_vector1.x+a_vector2.x,
00458 a_vector1.y+a_vector2.y,
00459 a_vector1.z+a_vector2.z);
00460 }
00461
00462
00463
00473
00474 inline cVector3d cAdd(const cVector3d& a_vector1, const cVector3d& a_vector2, const cVector3d& a_vector3)
00475 {
00476 return cVector3d(
00477 a_vector1.x+a_vector2.x+a_vector3.x,
00478 a_vector1.y+a_vector2.y+a_vector3.y,
00479 a_vector1.z+a_vector2.z+a_vector3.z);
00480 }
00481
00482
00483
00492
00493 inline cVector3d cSub(const cVector3d& a_vector1, const cVector3d& a_vector2)
00494 {
00495 return cVector3d(
00496 a_vector1.x-a_vector2.x,
00497 a_vector1.y-a_vector2.y,
00498 a_vector1.z-a_vector2.z);
00499 }
00500
00501
00502
00509
00510 inline cVector3d cNegate(const cVector3d& a_vector)
00511 {
00512 return cVector3d(a_vector.x*-1.0,a_vector.y*-1.0,a_vector.z*-1.0);
00513 }
00514
00515
00516
00524
00525 inline cVector3d cMul(const double& a_value, const cVector3d& a_vector)
00526 {
00527 return cVector3d(a_vector.x*a_value,a_vector.y*a_value,a_vector.z*a_value);
00528 }
00529
00530
00531
00539
00540 inline cVector3d cDiv(const double& a_value, const cVector3d& a_vector)
00541 {
00542 return cVector3d(a_vector.x/a_value,a_vector.y/a_value,a_vector.z/a_value);
00543 }
00544
00545
00546
00554
00555 inline cVector3d cDivVect(const double& a_value, const cVector3d& a_vector)
00556 {
00557 return cVector3d(
00558 a_value / a_vector.x,a_value / a_vector.y,a_value / a_vector.z
00559 );
00560 }
00561
00562
00563
00571
00572 inline cVector3d cCross(const cVector3d& a_vector1, const cVector3d& a_vector2)
00573 {
00574 cVector3d result;
00575 a_vector1.crossr(a_vector2, result);
00576 return (result);
00577 }
00578
00579
00580
00588
00589 inline double cDot(const cVector3d& a_vector1, const cVector3d& a_vector2)
00590 {
00591 return(a_vector1.dot(a_vector2));
00592 }
00593
00594
00595
00602
00603 inline cVector3d cNormalize(const cVector3d& a_vector)
00604 {
00605 cVector3d result;
00606 a_vector.normalizer(result);
00607 return (result);
00608 }
00609
00610
00611
00619
00620 inline double cDistance(const cVector3d& a_point1, const cVector3d& a_point2)
00621 {
00622 return ( a_point1.distance(a_point2) );
00623 }
00624
00625
00626
00634
00635 inline double cDistanceSq(const cVector3d& a_point1, const cVector3d& a_point2)
00636 {
00637 return ( a_point1.distancesq(a_point2) );
00638 }
00639
00640
00641
00655
00656 bool inline cEqualPoints(const cVector3d& v1,
00657 const cVector3d& v2,
00658 const double epsilon=CHAI_SMALL)
00659 {
00660
00661 if (epsilon == 0.0) {
00662 if ( (v1.x == v2.x) && (v1.y == v2.y) && (v1.z == v2.z) ) return true;
00663 else return false;
00664 }
00665
00666 if ((fabs(v1.x-v2.x) < epsilon) &&
00667 (fabs(v1.y-v2.y) < epsilon) &&
00668 (fabs(v1.z-v2.z) < epsilon)) return true;
00669 else return false;
00670 }
00671
00672
00673
00679
00680 inline cMatrix3d cIdentity3d(void)
00681 {
00682 cMatrix3d result;
00683 result.identity();
00684 return (result);
00685 }
00686
00687
00688
00696
00697 inline cMatrix3d cMul(const cMatrix3d& a_matrix1, const cMatrix3d& a_matrix2)
00698 {
00699 cMatrix3d result;
00700 a_matrix1.mulr(a_matrix2, result);
00701 return (result);
00702 }
00703
00704
00705
00713
00714 inline cVector3d cMul(const cMatrix3d& a_matrix, const cVector3d& a_vector)
00715 {
00716 cVector3d result;
00717 a_matrix.mulr(a_vector, result);
00718 return(result);
00719 }
00720
00721
00722
00729
00730 inline cMatrix3d cTrans(const cMatrix3d& a_matrix)
00731 {
00732 cMatrix3d result;
00733 a_matrix.transr(result);
00734 return(result);
00735 }
00736
00737
00738
00745
00746 inline cMatrix3d cInv(const cMatrix3d& a_matrix)
00747 {
00748 cMatrix3d result;
00749 a_matrix.invertr(result);
00750 return(result);
00751 }
00752
00753
00754
00762
00763 inline double cAngle(const cVector3d& a_vector0, const cVector3d& a_vector1)
00764 {
00765
00766 double n0 = a_vector0.length();
00767 double n1 = a_vector1.length();
00768 double val = n0 * n1;
00769
00770
00771 if (cAbs(val) < CHAI_SMALL)
00772 {
00773 return (0);
00774 }
00775
00776
00777 double result = a_vector0.dot(a_vector1)/(val);
00778 if (result > 1.0) { result = 1.0; }
00779 else if (result < -1.0) { result = -1.0; }
00780
00781 return(acos(result));
00782 }
00783
00784
00785
00793
00794 inline double cCosAngle(const cVector3d& a_vector0, const cVector3d& a_vector1)
00795 {
00796
00797 double n0 = a_vector0.length();
00798 double n1 = a_vector1.length();
00799 double val = n0 * n1;
00800
00801
00802 if (cAbs(val) < CHAI_SMALL)
00803 {
00804 return (0);
00805 }
00806
00807
00808 return(a_vector0.dot(a_vector1)/(val));
00809 }
00810
00811
00812
00820
00821 inline cMatrix3d cRotMatrix(const cVector3d& a_axis, const double& a_angleRad)
00822 {
00823 cMatrix3d result;
00824 result.set(a_axis, a_angleRad);
00825 return (result);
00826 }
00827
00828
00829
00838
00839 inline cMatrix3d cRotate(const cMatrix3d& a_matrix,
00840 const cVector3d& a_axis,
00841 const double& a_angleRad)
00842 {
00843 cMatrix3d result;
00844 a_matrix.rotater(a_axis, a_angleRad, result);
00845 return (result);
00846 }
00847
00848
00849
00859
00860 inline cVector3d cProjectPointOnPlane(const cVector3d& a_point,
00861 const cVector3d& a_planePoint,
00862 const cVector3d& n)
00863 {
00864
00865 cMatrix3d projectionMatrix;
00866
00867 projectionMatrix.set(
00868 (n.y * n.y) + (n.z * n.z), -(n.x * n.y), -(n.x * n.z),
00869 -(n.y * n.x), (n.x * n.x) + (n.z * n.z), -(n.y * n.z),
00870 -(n.z * n.x), -(n.z * n.y), (n.x * n.x) + (n.y * n.y) );
00871
00872
00873 cVector3d point;
00874 a_point.subr(a_planePoint, point);
00875 projectionMatrix.mul(point);
00876 point.add(a_planePoint);
00877
00878
00879 return (point);
00880 }
00881
00882
00883
00894
00895 inline cVector3d cProjectPointOnPlane(const cVector3d& a_point,
00896 const cVector3d& a_planePoint0, const cVector3d& a_planePoint1,
00897 const cVector3d& a_planePoint2)
00898 {
00899
00900
00901 cVector3d v01, v02;
00902 a_planePoint1.subr(a_planePoint0, v01);
00903 a_planePoint2.subr(a_planePoint0, v02);
00904
00905
00906 cVector3d n;
00907 v01.crossr(v02, n);
00908 n.normalize();
00909
00910 return cProjectPointOnPlane(a_point,a_planePoint0,n);
00911 }
00912
00913
00914
00931
00932 inline void cProjectPointOnPlane(const cVector3d& a_point,
00933 const cVector3d& a_planePoint0, const cVector3d& a_planePoint1,
00934 const cVector3d& a_planePoint2, double& a_v01, double a_v02)
00935 {
00936 cVector3d v01 = cSub(a_planePoint1, a_planePoint0);
00937 cVector3d v02 = cSub(a_planePoint2, a_planePoint0);
00938 cVector3d point = cSub(a_point, a_planePoint0);
00939
00940
00941 double m00 = v01.x * v01.x + v01.y * v01.y + v01.z * v01.z;
00942 double m01 = v01.x * v02.x + v01.y * v02.y + v01.z * v02.z;
00943 double m10 = m01;
00944 double m11 = v02.x * v02.x + v02.y * v02.y + v02.z * v02.z;
00945 double det = m00 * m11 - m10 * m01;
00946
00947
00948 double vm0 = v01.x * point.x + v01.y * point.y + v01.z * point.z;
00949 double vm1 = v02.x * point.x + v02.y * point.y + v02.z * point.z;
00950
00951
00952 a_v01 = (1.0 / det) * ( m11 * vm0 - m01 * vm1);
00953 a_v02 = (1.0 / det) * (-m10 * vm0 + m00 * vm1);
00954 }
00955
00956
00957
00967
00968 inline cVector3d cProjectPointOnLine(const cVector3d& a_point,
00969 const cVector3d& a_pointOnLine, const cVector3d& a_directionOfLine)
00970 {
00971
00972 cVector3d point, result;
00973
00974
00975 double lengthDirSq = a_directionOfLine.lengthsq();
00976 a_point.subr(a_pointOnLine, point);
00977
00978 a_directionOfLine.mulr( (point.dot(a_directionOfLine) / (lengthDirSq)),
00979 result);
00980
00981 result.add(a_pointOnLine);
00982
00983
00984 return (result);
00985 }
00986
00987
00988
00998
00999 inline cVector3d cProjectPointOnSegment(const cVector3d& a_point,
01000 const cVector3d& a_segmentPointA,
01001 const cVector3d& a_segmentPointB)
01002 {
01003
01004 if (a_segmentPointA.equals(a_segmentPointB))
01005 {
01006 return (a_segmentPointA);
01007 }
01008
01009
01010 cVector3d segmentAB;
01011 a_segmentPointB.subr(a_segmentPointA, segmentAB);
01012
01013
01014 cVector3d projection = cProjectPointOnLine(a_point, a_segmentPointA, segmentAB);
01015
01016 double distanceAB = segmentAB.lengthsq();
01017 double distanceAP = cDistanceSq(projection, a_segmentPointA);
01018 double distanceBP = cDistanceSq(projection, a_segmentPointB);
01019
01020 if (distanceAP > distanceAB)
01021 {
01022 return(a_segmentPointB);
01023 }
01024 else
01025 if (distanceBP > distanceAB)
01026 {
01027 return(a_segmentPointA);
01028 }
01029 else
01030 {
01031 return(projection);
01032 }
01033 }
01034
01035
01036
01037
01045
01046 inline cVector3d cProject(const cVector3d& a_vector0, const cVector3d& a_vector1)
01047 {
01048
01049 cVector3d result;
01050
01051
01052 double lengthSq = a_vector1.lengthsq();
01053 a_vector1.mulr( (a_vector0.dot(a_vector1) / (lengthSq)), result);
01054
01055
01056 return (result);
01057 }
01058
01059
01060
01070
01071 inline cVector3d cComputeSurfaceNormal(const cVector3d& a_surfacePoint0,
01072 const cVector3d& a_surfacePoint1, const cVector3d& a_surfacePoint2)
01073 {
01074
01075 cVector3d v01, v02, result;
01076
01077
01078 a_surfacePoint1.subr(a_surfacePoint0, v01);
01079 a_surfacePoint2.subr(a_surfacePoint0, v02);
01080 v01.normalize();
01081 v02.normalize();
01082 v01.crossr(v02, result);
01083 result.normalize();
01084
01085
01086 return (result);
01087 }
01088
01089
01098
01099 inline bool cBoxContains(const cVector3d& a_point, const cVector3d& box_min, const cVector3d& box_max)
01100 {
01101 if ((a_point.x >= box_min.x) && (a_point.x <= box_max.x) &&
01102 (a_point.y >= box_min.y) && (a_point.y <= box_max.y) &&
01103 (a_point.z >= box_min.z) && (a_point.z <= box_max.z))
01104 return true;
01105 return false;
01106 }
01107
01108
01109
01127
01128 inline int cIntersectionSegmentSphere(cVector3d& a_segmentPointA,
01129 cVector3d& a_segmentPointB,
01130 cVector3d& a_spherePos,
01131 double& a_sphereRadius,
01132 cVector3d& a_collisionPoint0,
01133 cVector3d& a_collisionNormal0,
01134 cVector3d& a_collisionPoint1,
01135 cVector3d& a_collisionNormal1)
01136 {
01137
01138 cVector3d AB, CA;
01139 a_segmentPointB.subr(a_segmentPointA, AB);
01140 a_segmentPointA.subr(a_spherePos, CA);
01141 double radiusSq = a_sphereRadius * a_sphereRadius;
01142
01143 double a = AB.lengthsq();
01144 double b = 2.0 * cDot(AB, CA);
01145 double c = CA.lengthsq() - radiusSq;
01146
01147
01148 if (a == 0)
01149 {
01150 return (0);
01151 }
01152
01153 double d = b*b - 4*a*c;
01154
01155
01156 if (d < 0)
01157 {
01158 return (0);
01159 }
01160
01161
01162 d = sqrt(d);
01163 double e = 2.0 * a;
01164
01165
01166 double u0 = (-b + d) / e;
01167 double u1 = (-b - d) / e;
01168
01169
01170 bool valid_u0 = cContains(u0, 0.0, 1.0);
01171 bool valid_u1 = cContains(u1, 0.0, 1.0);
01172
01173
01174 if (valid_u0 && valid_u1)
01175 {
01176 if (u0 > u1) { cSwap(u0, u1); }
01177
01178
01179 AB.mulr(u0, a_collisionPoint0);
01180 a_collisionPoint0.add(a_segmentPointA);
01181
01182 a_collisionPoint0.subr(a_spherePos, a_collisionNormal0);
01183 a_collisionNormal0.normalize();
01184
01185
01186 AB.mulr(u1, a_collisionPoint1);
01187 a_collisionPoint1.add(a_segmentPointA);
01188
01189 a_collisionPoint1.subr(a_spherePos, a_collisionNormal1);
01190 a_collisionNormal1.normalize();
01191
01192 return (2);
01193 }
01194
01195
01196 else if (valid_u0)
01197 {
01198
01199 AB.mulr(u0, a_collisionPoint0);
01200 a_collisionPoint0.add(a_segmentPointA);
01201
01202 a_collisionPoint0.subr(a_spherePos, a_collisionNormal0);
01203 a_collisionNormal0.normalize();
01204
01205 return (1);
01206 }
01207
01208
01209 else if (valid_u1)
01210 {
01211
01212 AB.mulr(u1, a_collisionPoint0);
01213 a_collisionPoint0.add(a_segmentPointA);
01214
01215 a_collisionPoint0.subr(a_spherePos, a_collisionNormal0);
01216 a_collisionNormal0.normalize();
01217
01218 return (1);
01219 }
01220
01221
01222 else
01223 {
01224 return (0);
01225 }
01226
01227 }
01228
01229
01230
01249
01250 inline int cIntersectionSegmentToplessCylinder(
01251 cVector3d& a_segmentPointA,
01252 cVector3d& a_segmentPointB,
01253 cVector3d& a_cylinderPointA,
01254 cVector3d& a_cylinderPointB,
01255 double& a_cylinderRadius,
01256 cVector3d& a_collisionPoint0,
01257 cVector3d& a_collisionNormal0,
01258 cVector3d& a_collisionPoint1,
01259 cVector3d& a_collisionNormal1)
01260 {
01261 cVector3d RC = a_segmentPointA - a_cylinderPointA;
01262 cVector3d segmentAB = a_segmentPointB - a_segmentPointA;
01263 cVector3d segmentDir = cNormalize(segmentAB);
01264 cVector3d cylinderDir = cNormalize(a_cylinderPointB - a_cylinderPointA);
01265 cVector3d n = cCross(segmentDir, cylinderDir);
01266
01267
01268 double length = n.length();
01269 if (length == 0.0)
01270 {
01271 return (0);
01272 }
01273
01274 n.normalize();
01275 double d = cAbs (cDot (RC,n));
01276
01277 if (d <= a_cylinderRadius)
01278 {
01279 cVector3d O = cCross(RC, cylinderDir);
01280 double t = -cDot(O,n) / length;
01281 O = cCross(n, cylinderDir);
01282 O.normalize();
01283 double s = cAbs(sqrt(a_cylinderRadius*a_cylinderRadius - d*d) / cDot(segmentDir,O));
01284 double u0 = t - s;
01285 double u1 = t + s;
01286
01287
01288 if (u0 > u1) { cSwap (u0,u1); }
01289
01290 bool valid_u0 = true;
01291 bool valid_u1 = true;
01292
01293
01294 double lengthAB = segmentAB.length();
01295 if (!cContains(u0, 0.0, lengthAB)) { valid_u0 = false; }
01296 if (!cContains(u1, 0.0, lengthAB)) { valid_u1 = false; }
01297
01298
01299 cVector3d P0, P1;
01300 cVector3d cylinderDirNeg = cNegate(cylinderDir);
01301
01302 if (valid_u0)
01303 {
01304 P0 = a_segmentPointA + u0 * segmentDir;
01305 double cosAngleA = cCosAngle(cylinderDir, cSub(P0, a_cylinderPointA));
01306 double cosAngleB = cCosAngle(cylinderDirNeg, cSub(P0, a_cylinderPointB));
01307
01308 if ((cosAngleA <= 0.0) || (cosAngleB <= 0.0))
01309 {
01310 valid_u0 = false;
01311 }
01312 }
01313
01314 if (valid_u1)
01315 {
01316 P1 = a_segmentPointA + u1 * segmentDir;
01317 double cosAngleA = cCosAngle(cylinderDir, cSub(P1, a_cylinderPointA));
01318 double cosAngleB = cCosAngle(cylinderDirNeg, cSub(P1, a_cylinderPointB));
01319
01320 if ((cosAngleA <= 0.0) || (cosAngleB <= 0.0))
01321 {
01322 valid_u1 = false;
01323 }
01324 }
01325
01326 if (valid_u0 && valid_u1)
01327 {
01328 a_collisionPoint0 = P0;
01329 a_collisionNormal0 = cNormalize(cCross(cylinderDir, cCross(cSub(P0, a_cylinderPointA), cylinderDir)));
01330 a_collisionPoint1 = P1;
01331 a_collisionNormal1 = cNormalize(cCross(cylinderDir, cCross(cSub(P1, a_cylinderPointA), cylinderDir)));
01332 return (2);
01333 }
01334 else if (valid_u0)
01335 {
01336 a_collisionPoint0 = P0;
01337 a_collisionNormal0 = cNormalize(cCross(cylinderDir, cCross(cSub(P0, a_cylinderPointA), cylinderDir)));
01338 return (1);
01339 }
01340 else if (valid_u1)
01341 {
01342 a_collisionPoint0 = P1;
01343 a_collisionNormal0 = cNormalize(cCross(cylinderDir, cCross(cSub(P1, a_cylinderPointA), cylinderDir)));
01344 return (1);
01345 }
01346 }
01347
01348 return (0);
01349 }
01350
01351
01352
01366
01367 inline bool cIntersectionSegmentTriangle(
01368 cVector3d& a_segmentPointA,
01369 cVector3d& a_segmentPointB,
01370 cVector3d& a_triangleVertex0,
01371 cVector3d& a_triangleVertex1,
01372 cVector3d& a_triangleVertex2,
01373 cVector3d& a_collisionPoint,
01374 cVector3d& a_collisionNormal)
01375 {
01376
01377
01378 const double CHAI_INTERSECT_EPSILON = 10e-14f;
01379
01380
01381 cVector3d rayDir;
01382 a_segmentPointB.subr(a_segmentPointA, rayDir);
01383 double segmentLengthSquare = rayDir.lengthsq();
01384 if (segmentLengthSquare == 0.0) { return (false); }
01385
01386
01387 cVector3d t_E0, t_E1, t_N;
01388
01389 a_triangleVertex1.subr(a_triangleVertex0, t_E0);
01390 a_triangleVertex2.subr(a_triangleVertex0, t_E1);
01391 t_E0.crossr(t_E1, t_N);
01392
01393
01394
01395 if (fabs(t_N.dot(rayDir))<10E-15f) return (false);
01396
01397 double t_T = cDot(t_N, cSub(a_triangleVertex0, a_segmentPointA)) / cDot(t_N, rayDir);
01398
01399 if (t_T + CHAI_INTERSECT_EPSILON < 0) return (false);
01400
01401 cVector3d t_Q = cSub(cAdd(a_segmentPointA, cMul(t_T, rayDir)), a_triangleVertex0);
01402 double t_Q0 = cDot(t_E0,t_Q);
01403 double t_Q1 = cDot(t_E1,t_Q);
01404 double t_E00 = cDot(t_E0,t_E0);
01405 double t_E01 = cDot(t_E0,t_E1);
01406 double t_E11 = cDot(t_E1,t_E1);
01407 double t_D = (t_E00 * t_E11) - (t_E01 * t_E01);
01408
01409 if ((t_D > -CHAI_INTERSECT_EPSILON) && (t_D < CHAI_INTERSECT_EPSILON)) return(false);
01410
01411 double t_S0 = ((t_E11 * t_Q0) - (t_E01 * t_Q1)) / t_D;
01412 double t_S1 = ((t_E00 * t_Q1) - (t_E01 * t_Q0)) / t_D;
01413
01414
01415 if (
01416 (t_S0 >= 0.0 - CHAI_INTERSECT_EPSILON) &&
01417 (t_S1 >= 0.0 - CHAI_INTERSECT_EPSILON) &&
01418 ((t_S0 + t_S1) <= 1.0 + CHAI_INTERSECT_EPSILON)
01419 )
01420 {
01421 cVector3d t_I = cAdd(a_triangleVertex0, cMul(t_S0,t_E0), cMul(t_S1, t_E1));
01422
01423
01424 double distanceSquare = a_segmentPointA.distancesq(t_I);
01425
01426
01427 if (distanceSquare <= segmentLengthSquare)
01428 {
01429 a_collisionPoint = cAdd(a_segmentPointA, cMul(t_T, rayDir));
01430 t_N.normalizer(a_collisionNormal);
01431 if (cCosAngle(a_collisionNormal, rayDir) > 0.0)
01432 {
01433 a_collisionNormal.negate();
01434 }
01435 return (true);
01436 }
01437 }
01438
01439
01440 return (false);
01441 }
01442
01443
01444
01445 #endif
01446
01447
01448