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.
8 // Original code by David Eberly in Magic.
9 BOOL
SphereCollider::SphereTriOverlap(const Point
& vert0
, const Point
& vert1
, const Point
& vert2
)
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
;
19 kDiff
= vert1
- mCenter
;
20 fC
= kDiff
.SquareMagnitude();
21 if(fC
<= mRadius2
) return TRUE
;
23 kDiff
= vert0
- mCenter
;
24 fC
= kDiff
.SquareMagnitude();
25 if(fC
<= mRadius2
) return TRUE
;
27 // Else do the full distance test
28 Point TriEdge0
= vert1
- vert0
;
29 Point TriEdge1
= vert2
- vert0
;
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
;
47 if(v
< 0.0f
) // region 4
52 if(-fB0
>=fA00
) { /*u = 1.0f;*/ SqrDist
= fA00
+2.0f
*fB0
+fC
; }
53 else { u
= -fB0
/fA00
; SqrDist
= fB0
*u
+fC
; }
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
; }
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
; }
71 else if(v
< 0.0f
) // region 5
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
; }
80 // minimum at interior point
89 float fInvDet
= 1.0f
/fDet
;
92 SqrDist
= u
*(fA00
*u
+fA01
*v
+2.0f
*fB0
) + v
*(fA01
*u
+fA11
*v
+2.0f
*fB1
)+fC
;
98 float fTmp0
, fTmp1
, fNumer
, fDenom
;
100 if(u
< 0.0f
) // region 2
106 fNumer
= fTmp1
- fTmp0
;
107 fDenom
= fA00
-2.0f
*fA01
+fA11
;
112 SqrDist
= fA00
+2.0f
*fB0
+fC
;
118 SqrDist
= u
*(fA00
*u
+fA01
*v
+2.0f
*fB0
) + v
*(fA01
*u
+fA11
*v
+2.0f
*fB1
)+fC
;
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
; }
129 else if(v
< 0.0f
) // region 6
135 fNumer
= fTmp1
- fTmp0
;
136 fDenom
= fA00
-2.0f
*fA01
+fA11
;
141 SqrDist
= fA11
+2.0f
*fB1
+fC
;
147 SqrDist
= u
*(fA00
*u
+fA01
*v
+2.0f
*fB0
) + v
*(fA01
*u
+fA11
*v
+2.0f
*fB1
)+fC
;
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
; }
160 fNumer
= fA11
+ fB1
- fA01
- fB0
;
165 SqrDist
= fA11
+2.0f
*fB1
+fC
;
169 fDenom
= fA00
-2.0f
*fA01
+fA11
;
174 SqrDist
= fA00
+2.0f
*fB0
+fC
;
180 SqrDist
= u
*(fA00
*u
+fA01
*v
+2.0f
*fB0
) + v
*(fA01
*u
+fA11
*v
+2.0f
*fB1
)+fC
;
186 return fabsf(SqrDist
) < mRadius2
;