| [216] | 1 |  | 
|---|
 | 2 | // This is collision detection. If you do another distance test for collision *response*, | 
|---|
 | 3 | // if might be useful to simply *skip* the test below completely, and report a collision. | 
|---|
 | 4 | // - if sphere-triangle overlap, result is ok | 
|---|
 | 5 | // - if they don't, we'll discard them during collision response with a similar test anyway | 
|---|
 | 6 | // Overall this approach should run faster. | 
|---|
 | 7 |  | 
|---|
 | 8 | // Original code by David Eberly in Magic. | 
|---|
 | 9 | BOOL SphereCollider::SphereTriOverlap(const Point& vert0, const Point& vert1, const Point& vert2) | 
|---|
 | 10 | { | 
|---|
 | 11 |         // Stats | 
|---|
 | 12 |         mNbVolumePrimTests++; | 
|---|
 | 13 |  | 
|---|
 | 14 |         // Early exit if one of the vertices is inside the sphere | 
|---|
 | 15 |         Point kDiff = vert2 - mCenter; | 
|---|
 | 16 |         float fC = kDiff.SquareMagnitude(); | 
|---|
 | 17 |         if(fC <= mRadius2)      return TRUE; | 
|---|
 | 18 |  | 
|---|
 | 19 |         kDiff = vert1 - mCenter; | 
|---|
 | 20 |         fC = kDiff.SquareMagnitude(); | 
|---|
 | 21 |         if(fC <= mRadius2)      return TRUE; | 
|---|
 | 22 |  | 
|---|
 | 23 |         kDiff = vert0 - mCenter; | 
|---|
 | 24 |         fC = kDiff.SquareMagnitude(); | 
|---|
 | 25 |         if(fC <= mRadius2)      return TRUE; | 
|---|
 | 26 |  | 
|---|
 | 27 |         // Else do the full distance test | 
|---|
 | 28 |         Point TriEdge0  = vert1 - vert0; | 
|---|
 | 29 |         Point TriEdge1  = vert2 - vert0; | 
|---|
 | 30 |  | 
|---|
 | 31 | //Point kDiff   = vert0 - mCenter; | 
|---|
 | 32 |         float fA00      = TriEdge0.SquareMagnitude(); | 
|---|
 | 33 |         float fA01      = TriEdge0 | TriEdge1; | 
|---|
 | 34 |         float fA11      = TriEdge1.SquareMagnitude(); | 
|---|
 | 35 |         float fB0       = kDiff | TriEdge0; | 
|---|
 | 36 |         float fB1       = kDiff | TriEdge1; | 
|---|
 | 37 | //float fC      = kDiff.SquareMagnitude(); | 
|---|
 | 38 |         float fDet      = fabsf(fA00*fA11 - fA01*fA01); | 
|---|
 | 39 |         float u         = fA01*fB1-fA11*fB0; | 
|---|
 | 40 |         float v         = fA01*fB0-fA00*fB1; | 
|---|
 | 41 |         float SqrDist; | 
|---|
 | 42 |  | 
|---|
 | 43 |         if(u + v <= fDet) | 
|---|
 | 44 |         { | 
|---|
 | 45 |                 if(u < 0.0f) | 
|---|
 | 46 |                 { | 
|---|
 | 47 |                         if(v < 0.0f)  // region 4 | 
|---|
 | 48 |                         { | 
|---|
 | 49 |                                 if(fB0 < 0.0f) | 
|---|
 | 50 |                                 { | 
|---|
 | 51 | //                                      v = 0.0f; | 
|---|
 | 52 |                                         if(-fB0>=fA00)                  { /*u = 1.0f;*/         SqrDist = fA00+2.0f*fB0+fC;     } | 
|---|
 | 53 |                                         else                                    { u = -fB0/fA00;        SqrDist = fB0*u+fC;                     } | 
|---|
 | 54 |                                 } | 
|---|
 | 55 |                                 else | 
|---|
 | 56 |                                 { | 
|---|
 | 57 | //                                      u = 0.0f; | 
|---|
 | 58 |                                         if(fB1>=0.0f)                   { /*v = 0.0f;*/         SqrDist = fC;                           } | 
|---|
 | 59 |                                         else if(-fB1>=fA11)             { /*v = 1.0f;*/         SqrDist = fA11+2.0f*fB1+fC;     } | 
|---|
 | 60 |                                         else                                    { v = -fB1/fA11;        SqrDist = fB1*v+fC;                     } | 
|---|
 | 61 |                                 } | 
|---|
 | 62 |                         } | 
|---|
 | 63 |                         else  // region 3 | 
|---|
 | 64 |                         { | 
|---|
 | 65 | //                              u = 0.0f; | 
|---|
 | 66 |                                 if(fB1>=0.0f)                           { /*v = 0.0f;*/         SqrDist = fC;                           } | 
|---|
 | 67 |                                 else if(-fB1>=fA11)                     { /*v = 1.0f;*/         SqrDist = fA11+2.0f*fB1+fC;     } | 
|---|
 | 68 |                                 else                                            { v = -fB1/fA11;        SqrDist = fB1*v+fC;                     } | 
|---|
 | 69 |                         } | 
|---|
 | 70 |                 } | 
|---|
 | 71 |                 else if(v < 0.0f)  // region 5 | 
|---|
 | 72 |                 { | 
|---|
 | 73 | //                      v = 0.0f; | 
|---|
 | 74 |                         if(fB0>=0.0f)                                   { /*u = 0.0f;*/         SqrDist = fC;                           } | 
|---|
 | 75 |                         else if(-fB0>=fA00)                             { /*u = 1.0f;*/         SqrDist = fA00+2.0f*fB0+fC;     } | 
|---|
 | 76 |                         else                                                    { u = -fB0/fA00;        SqrDist = fB0*u+fC;                     } | 
|---|
 | 77 |                 } | 
|---|
 | 78 |                 else  // region 0 | 
|---|
 | 79 |                 { | 
|---|
 | 80 |                         // minimum at interior point | 
|---|
 | 81 |                         if(fDet==0.0f) | 
|---|
 | 82 |                         { | 
|---|
 | 83 | //                              u = 0.0f; | 
|---|
 | 84 | //                              v = 0.0f; | 
|---|
 | 85 |                                 SqrDist = MAX_FLOAT; | 
|---|
 | 86 |                         } | 
|---|
 | 87 |                         else | 
|---|
 | 88 |                         { | 
|---|
 | 89 |                                 float fInvDet = 1.0f/fDet; | 
|---|
 | 90 |                                 u *= fInvDet; | 
|---|
 | 91 |                                 v *= fInvDet; | 
|---|
 | 92 |                                 SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; | 
|---|
 | 93 |                         } | 
|---|
 | 94 |                 } | 
|---|
 | 95 |         } | 
|---|
 | 96 |         else | 
|---|
 | 97 |         { | 
|---|
 | 98 |                 float fTmp0, fTmp1, fNumer, fDenom; | 
|---|
 | 99 |  | 
|---|
 | 100 |                 if(u < 0.0f)  // region 2 | 
|---|
 | 101 |                 { | 
|---|
 | 102 |                         fTmp0 = fA01 + fB0; | 
|---|
 | 103 |                         fTmp1 = fA11 + fB1; | 
|---|
 | 104 |                         if(fTmp1 > fTmp0) | 
|---|
 | 105 |                         { | 
|---|
 | 106 |                                 fNumer = fTmp1 - fTmp0; | 
|---|
 | 107 |                                 fDenom = fA00-2.0f*fA01+fA11; | 
|---|
 | 108 |                                 if(fNumer >= fDenom) | 
|---|
 | 109 |                                 { | 
|---|
 | 110 | //                                      u = 1.0f; | 
|---|
 | 111 | //                                      v = 0.0f; | 
|---|
 | 112 |                                         SqrDist = fA00+2.0f*fB0+fC; | 
|---|
 | 113 |                                 } | 
|---|
 | 114 |                                 else | 
|---|
 | 115 |                                 { | 
|---|
 | 116 |                                         u = fNumer/fDenom; | 
|---|
 | 117 |                                         v = 1.0f - u; | 
|---|
 | 118 |                                         SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; | 
|---|
 | 119 |                                 } | 
|---|
 | 120 |                         } | 
|---|
 | 121 |                         else | 
|---|
 | 122 |                         { | 
|---|
 | 123 | //                              u = 0.0f; | 
|---|
 | 124 |                                 if(fTmp1 <= 0.0f)               { /*v = 1.0f;*/         SqrDist = fA11+2.0f*fB1+fC;     } | 
|---|
 | 125 |                                 else if(fB1 >= 0.0f)    { /*v = 0.0f;*/         SqrDist = fC;                           } | 
|---|
 | 126 |                                 else                                    { v = -fB1/fA11;        SqrDist = fB1*v+fC;                     } | 
|---|
 | 127 |                         } | 
|---|
 | 128 |                 } | 
|---|
 | 129 |                 else if(v < 0.0f)  // region 6 | 
|---|
 | 130 |                 { | 
|---|
 | 131 |                         fTmp0 = fA01 + fB1; | 
|---|
 | 132 |                         fTmp1 = fA00 + fB0; | 
|---|
 | 133 |                         if(fTmp1 > fTmp0) | 
|---|
 | 134 |                         { | 
|---|
 | 135 |                                 fNumer = fTmp1 - fTmp0; | 
|---|
 | 136 |                                 fDenom = fA00-2.0f*fA01+fA11; | 
|---|
 | 137 |                                 if(fNumer >= fDenom) | 
|---|
 | 138 |                                 { | 
|---|
 | 139 | //                                      v = 1.0f; | 
|---|
 | 140 | //                                      u = 0.0f; | 
|---|
 | 141 |                                         SqrDist = fA11+2.0f*fB1+fC; | 
|---|
 | 142 |                                 } | 
|---|
 | 143 |                                 else | 
|---|
 | 144 |                                 { | 
|---|
 | 145 |                                         v = fNumer/fDenom; | 
|---|
 | 146 |                                         u = 1.0f - v; | 
|---|
 | 147 |                                         SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; | 
|---|
 | 148 |                                 } | 
|---|
 | 149 |                         } | 
|---|
 | 150 |                         else | 
|---|
 | 151 |                         { | 
|---|
 | 152 | //                              v = 0.0f; | 
|---|
 | 153 |                                 if(fTmp1 <= 0.0f)               { /*u = 1.0f;*/         SqrDist = fA00+2.0f*fB0+fC;     } | 
|---|
 | 154 |                                 else if(fB0 >= 0.0f)    { /*u = 0.0f;*/         SqrDist = fC;                           } | 
|---|
 | 155 |                                 else                                    { u = -fB0/fA00;        SqrDist = fB0*u+fC;                     } | 
|---|
 | 156 |                         } | 
|---|
 | 157 |                 } | 
|---|
 | 158 |                 else  // region 1 | 
|---|
 | 159 |                 { | 
|---|
 | 160 |                         fNumer = fA11 + fB1 - fA01 - fB0; | 
|---|
 | 161 |                         if(fNumer <= 0.0f) | 
|---|
 | 162 |                         { | 
|---|
 | 163 | //                              u = 0.0f; | 
|---|
 | 164 | //                              v = 1.0f; | 
|---|
 | 165 |                                 SqrDist = fA11+2.0f*fB1+fC; | 
|---|
 | 166 |                         } | 
|---|
 | 167 |                         else | 
|---|
 | 168 |                         { | 
|---|
 | 169 |                                 fDenom = fA00-2.0f*fA01+fA11; | 
|---|
 | 170 |                                 if(fNumer >= fDenom) | 
|---|
 | 171 |                                 { | 
|---|
 | 172 | //                                      u = 1.0f; | 
|---|
 | 173 | //                                      v = 0.0f; | 
|---|
 | 174 |                                         SqrDist = fA00+2.0f*fB0+fC; | 
|---|
 | 175 |                                 } | 
|---|
 | 176 |                                 else | 
|---|
 | 177 |                                 { | 
|---|
 | 178 |                                         u = fNumer/fDenom; | 
|---|
 | 179 |                                         v = 1.0f - u; | 
|---|
 | 180 |                                         SqrDist = u*(fA00*u+fA01*v+2.0f*fB0) + v*(fA01*u+fA11*v+2.0f*fB1)+fC; | 
|---|
 | 181 |                                 } | 
|---|
 | 182 |                         } | 
|---|
 | 183 |                 } | 
|---|
 | 184 |         } | 
|---|
 | 185 |  | 
|---|
 | 186 |         return fabsf(SqrDist) < mRadius2; | 
|---|
 | 187 | } | 
|---|