2 // Following code from Magic-Software (http://www.magic-software.com/)
3 // A bit modified for Opcode
5 inline_
float OPC_PointAABBSqrDist(const Point
& point
, const Point
& center
, const Point
& extents
)
7 // Compute coordinates of point in box coordinate system
8 Point Closest
= point
- center
;
10 float SqrDistance
= 0.0f
;
12 if(Closest
.x
< -extents
.x
)
14 float Delta
= Closest
.x
+ extents
.x
;
15 SqrDistance
+= Delta
*Delta
;
17 else if(Closest
.x
> extents
.x
)
19 float Delta
= Closest
.x
- extents
.x
;
20 SqrDistance
+= Delta
*Delta
;
23 if(Closest
.y
< -extents
.y
)
25 float Delta
= Closest
.y
+ extents
.y
;
26 SqrDistance
+= Delta
*Delta
;
28 else if(Closest
.y
> extents
.y
)
30 float Delta
= Closest
.y
- extents
.y
;
31 SqrDistance
+= Delta
*Delta
;
34 if(Closest
.z
< -extents
.z
)
36 float Delta
= Closest
.z
+ extents
.z
;
37 SqrDistance
+= Delta
*Delta
;
39 else if(Closest
.z
> extents
.z
)
41 float Delta
= Closest
.z
- extents
.z
;
42 SqrDistance
+= Delta
*Delta
;
47 static void Face(int i0
, int i1
, int i2
, Point
& rkPnt
, const Point
& rkDir
, const Point
& extents
, const Point
& rkPmE
, float* pfLParam
, float& rfSqrDistance
)
50 float fLSqr
, fInv
, fTmp
, fParam
, fT
, fDelta
;
52 kPpE
[i1
] = rkPnt
[i1
] + extents
[i1
];
53 kPpE
[i2
] = rkPnt
[i2
] + extents
[i2
];
54 if(rkDir
[i0
]*kPpE
[i1
] >= rkDir
[i1
]*rkPmE
[i0
])
56 if(rkDir
[i0
]*kPpE
[i2
] >= rkDir
[i2
]*rkPmE
[i0
])
58 // v[i1] >= -e[i1], v[i2] >= -e[i2] (distance = 0)
61 rkPnt
[i0
] = extents
[i0
];
62 fInv
= 1.0f
/rkDir
[i0
];
63 rkPnt
[i1
] -= rkDir
[i1
]*rkPmE
[i0
]*fInv
;
64 rkPnt
[i2
] -= rkDir
[i2
]*rkPmE
[i0
]*fInv
;
65 *pfLParam
= -rkPmE
[i0
]*fInv
;
70 // v[i1] >= -e[i1], v[i2] < -e[i2]
71 fLSqr
= rkDir
[i0
]*rkDir
[i0
] + rkDir
[i2
]*rkDir
[i2
];
72 fTmp
= fLSqr
*kPpE
[i1
] - rkDir
[i1
]*(rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i2
]*kPpE
[i2
]);
73 if(fTmp
<= 2.0f
*fLSqr
*extents
[i1
])
76 fLSqr
+= rkDir
[i1
]*rkDir
[i1
];
78 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*fTmp
+ rkDir
[i2
]*kPpE
[i2
];
79 fParam
= -fDelta
/fLSqr
;
80 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + fTmp
*fTmp
+ kPpE
[i2
]*kPpE
[i2
] + fDelta
*fParam
;
85 rkPnt
[i0
] = extents
[i0
];
86 rkPnt
[i1
] = fT
- extents
[i1
];
87 rkPnt
[i2
] = -extents
[i2
];
92 fLSqr
+= rkDir
[i1
]*rkDir
[i1
];
93 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*rkPmE
[i1
] + rkDir
[i2
]*kPpE
[i2
];
94 fParam
= -fDelta
/fLSqr
;
95 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + rkPmE
[i1
]*rkPmE
[i1
] + kPpE
[i2
]*kPpE
[i2
] + fDelta
*fParam
;
100 rkPnt
[i0
] = extents
[i0
];
101 rkPnt
[i1
] = extents
[i1
];
102 rkPnt
[i2
] = -extents
[i2
];
109 if ( rkDir
[i0
]*kPpE
[i2
] >= rkDir
[i2
]*rkPmE
[i0
] )
111 // v[i1] < -e[i1], v[i2] >= -e[i2]
112 fLSqr
= rkDir
[i0
]*rkDir
[i0
] + rkDir
[i1
]*rkDir
[i1
];
113 fTmp
= fLSqr
*kPpE
[i2
] - rkDir
[i2
]*(rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
]);
114 if(fTmp
<= 2.0f
*fLSqr
*extents
[i2
])
117 fLSqr
+= rkDir
[i2
]*rkDir
[i2
];
118 fTmp
= kPpE
[i2
] - fT
;
119 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
] + rkDir
[i2
]*fTmp
;
120 fParam
= -fDelta
/fLSqr
;
121 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + kPpE
[i1
]*kPpE
[i1
] + fTmp
*fTmp
+ fDelta
*fParam
;
126 rkPnt
[i0
] = extents
[i0
];
127 rkPnt
[i1
] = -extents
[i1
];
128 rkPnt
[i2
] = fT
- extents
[i2
];
133 fLSqr
+= rkDir
[i2
]*rkDir
[i2
];
134 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
] + rkDir
[i2
]*rkPmE
[i2
];
135 fParam
= -fDelta
/fLSqr
;
136 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + kPpE
[i1
]*kPpE
[i1
] + rkPmE
[i2
]*rkPmE
[i2
] + fDelta
*fParam
;
141 rkPnt
[i0
] = extents
[i0
];
142 rkPnt
[i1
] = -extents
[i1
];
143 rkPnt
[i2
] = extents
[i2
];
149 // v[i1] < -e[i1], v[i2] < -e[i2]
150 fLSqr
= rkDir
[i0
]*rkDir
[i0
]+rkDir
[i2
]*rkDir
[i2
];
151 fTmp
= fLSqr
*kPpE
[i1
] - rkDir
[i1
]*(rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i2
]*kPpE
[i2
]);
154 // v[i1]-edge is closest
155 if ( fTmp
<= 2.0f
*fLSqr
*extents
[i1
] )
158 fLSqr
+= rkDir
[i1
]*rkDir
[i1
];
159 fTmp
= kPpE
[i1
] - fT
;
160 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*fTmp
+ rkDir
[i2
]*kPpE
[i2
];
161 fParam
= -fDelta
/fLSqr
;
162 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + fTmp
*fTmp
+ kPpE
[i2
]*kPpE
[i2
] + fDelta
*fParam
;
167 rkPnt
[i0
] = extents
[i0
];
168 rkPnt
[i1
] = fT
- extents
[i1
];
169 rkPnt
[i2
] = -extents
[i2
];
174 fLSqr
+= rkDir
[i1
]*rkDir
[i1
];
175 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*rkPmE
[i1
] + rkDir
[i2
]*kPpE
[i2
];
176 fParam
= -fDelta
/fLSqr
;
177 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + rkPmE
[i1
]*rkPmE
[i1
] + kPpE
[i2
]*kPpE
[i2
] + fDelta
*fParam
;
182 rkPnt
[i0
] = extents
[i0
];
183 rkPnt
[i1
] = extents
[i1
];
184 rkPnt
[i2
] = -extents
[i2
];
190 fLSqr
= rkDir
[i0
]*rkDir
[i0
] + rkDir
[i1
]*rkDir
[i1
];
191 fTmp
= fLSqr
*kPpE
[i2
] - rkDir
[i2
]*(rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
]);
194 // v[i2]-edge is closest
195 if(fTmp
<= 2.0f
*fLSqr
*extents
[i2
])
198 fLSqr
+= rkDir
[i2
]*rkDir
[i2
];
199 fTmp
= kPpE
[i2
] - fT
;
200 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
] + rkDir
[i2
]*fTmp
;
201 fParam
= -fDelta
/fLSqr
;
202 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + kPpE
[i1
]*kPpE
[i1
] + fTmp
*fTmp
+ fDelta
*fParam
;
207 rkPnt
[i0
] = extents
[i0
];
208 rkPnt
[i1
] = -extents
[i1
];
209 rkPnt
[i2
] = fT
- extents
[i2
];
214 fLSqr
+= rkDir
[i2
]*rkDir
[i2
];
215 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
] + rkDir
[i2
]*rkPmE
[i2
];
216 fParam
= -fDelta
/fLSqr
;
217 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + kPpE
[i1
]*kPpE
[i1
] + rkPmE
[i2
]*rkPmE
[i2
] + fDelta
*fParam
;
222 rkPnt
[i0
] = extents
[i0
];
223 rkPnt
[i1
] = -extents
[i1
];
224 rkPnt
[i2
] = extents
[i2
];
230 // (v[i1],v[i2])-corner is closest
231 fLSqr
+= rkDir
[i2
]*rkDir
[i2
];
232 fDelta
= rkDir
[i0
]*rkPmE
[i0
] + rkDir
[i1
]*kPpE
[i1
] + rkDir
[i2
]*kPpE
[i2
];
233 fParam
= -fDelta
/fLSqr
;
234 rfSqrDistance
+= rkPmE
[i0
]*rkPmE
[i0
] + kPpE
[i1
]*kPpE
[i1
] + kPpE
[i2
]*kPpE
[i2
] + fDelta
*fParam
;
239 rkPnt
[i0
] = extents
[i0
];
240 rkPnt
[i1
] = -extents
[i1
];
241 rkPnt
[i2
] = -extents
[i2
];
247 static void CaseNoZeros(Point
& rkPnt
, const Point
& rkDir
, const Point
& extents
, float* pfLParam
, float& rfSqrDistance
)
249 Point
kPmE(rkPnt
.x
- extents
.x
, rkPnt
.y
- extents
.y
, rkPnt
.z
- extents
.z
);
251 float fProdDxPy
, fProdDyPx
, fProdDzPx
, fProdDxPz
, fProdDzPy
, fProdDyPz
;
253 fProdDxPy
= rkDir
.x
*kPmE
.y
;
254 fProdDyPx
= rkDir
.y
*kPmE
.x
;
255 if(fProdDyPx
>= fProdDxPy
)
257 fProdDzPx
= rkDir
.z
*kPmE
.x
;
258 fProdDxPz
= rkDir
.x
*kPmE
.z
;
259 if(fProdDzPx
>= fProdDxPz
)
261 // line intersects x = e0
262 Face(0, 1, 2, rkPnt
, rkDir
, extents
, kPmE
, pfLParam
, rfSqrDistance
);
266 // line intersects z = e2
267 Face(2, 0, 1, rkPnt
, rkDir
, extents
, kPmE
, pfLParam
, rfSqrDistance
);
272 fProdDzPy
= rkDir
.z
*kPmE
.y
;
273 fProdDyPz
= rkDir
.y
*kPmE
.z
;
274 if(fProdDzPy
>= fProdDyPz
)
276 // line intersects y = e1
277 Face(1, 2, 0, rkPnt
, rkDir
, extents
, kPmE
, pfLParam
, rfSqrDistance
);
281 // line intersects z = e2
282 Face(2, 0, 1, rkPnt
, rkDir
, extents
, kPmE
, pfLParam
, rfSqrDistance
);
287 static void Case0(int i0
, int i1
, int i2
, Point
& rkPnt
, const Point
& rkDir
, const Point
& extents
, float* pfLParam
, float& rfSqrDistance
)
289 float fPmE0
= rkPnt
[i0
] - extents
[i0
];
290 float fPmE1
= rkPnt
[i1
] - extents
[i1
];
291 float fProd0
= rkDir
[i1
]*fPmE0
;
292 float fProd1
= rkDir
[i0
]*fPmE1
;
293 float fDelta
, fInvLSqr
, fInv
;
297 // line intersects P[i0] = e[i0]
298 rkPnt
[i0
] = extents
[i0
];
300 float fPpE1
= rkPnt
[i1
] + extents
[i1
];
301 fDelta
= fProd0
- rkDir
[i0
]*fPpE1
;
304 fInvLSqr
= 1.0f
/(rkDir
[i0
]*rkDir
[i0
] + rkDir
[i1
]*rkDir
[i1
]);
305 rfSqrDistance
+= fDelta
*fDelta
*fInvLSqr
;
308 rkPnt
[i1
] = -extents
[i1
];
309 *pfLParam
= -(rkDir
[i0
]*fPmE0
+rkDir
[i1
]*fPpE1
)*fInvLSqr
;
316 fInv
= 1.0f
/rkDir
[i0
];
317 rkPnt
[i1
] -= fProd0
*fInv
;
318 *pfLParam
= -fPmE0
*fInv
;
324 // line intersects P[i1] = e[i1]
325 rkPnt
[i1
] = extents
[i1
];
327 float fPpE0
= rkPnt
[i0
] + extents
[i0
];
328 fDelta
= fProd1
- rkDir
[i1
]*fPpE0
;
331 fInvLSqr
= 1.0f
/(rkDir
[i0
]*rkDir
[i0
] + rkDir
[i1
]*rkDir
[i1
]);
332 rfSqrDistance
+= fDelta
*fDelta
*fInvLSqr
;
335 rkPnt
[i0
] = -extents
[i0
];
336 *pfLParam
= -(rkDir
[i0
]*fPpE0
+rkDir
[i1
]*fPmE1
)*fInvLSqr
;
343 fInv
= 1.0f
/rkDir
[i1
];
344 rkPnt
[i0
] -= fProd1
*fInv
;
345 *pfLParam
= -fPmE1
*fInv
;
350 if(rkPnt
[i2
] < -extents
[i2
])
352 fDelta
= rkPnt
[i2
] + extents
[i2
];
353 rfSqrDistance
+= fDelta
*fDelta
;
354 rkPnt
[i2
] = -extents
[i2
];
356 else if ( rkPnt
[i2
] > extents
[i2
] )
358 fDelta
= rkPnt
[i2
] - extents
[i2
];
359 rfSqrDistance
+= fDelta
*fDelta
;
360 rkPnt
[i2
] = extents
[i2
];
364 static void Case00(int i0
, int i1
, int i2
, Point
& rkPnt
, const Point
& rkDir
, const Point
& extents
, float* pfLParam
, float& rfSqrDistance
)
369 *pfLParam
= (extents
[i0
] - rkPnt
[i0
])/rkDir
[i0
];
371 rkPnt
[i0
] = extents
[i0
];
373 if(rkPnt
[i1
] < -extents
[i1
])
375 fDelta
= rkPnt
[i1
] + extents
[i1
];
376 rfSqrDistance
+= fDelta
*fDelta
;
377 rkPnt
[i1
] = -extents
[i1
];
379 else if(rkPnt
[i1
] > extents
[i1
])
381 fDelta
= rkPnt
[i1
] - extents
[i1
];
382 rfSqrDistance
+= fDelta
*fDelta
;
383 rkPnt
[i1
] = extents
[i1
];
386 if(rkPnt
[i2
] < -extents
[i2
])
388 fDelta
= rkPnt
[i2
] + extents
[i2
];
389 rfSqrDistance
+= fDelta
*fDelta
;
390 rkPnt
[i1
] = -extents
[i2
];
392 else if(rkPnt
[i2
] > extents
[i2
])
394 fDelta
= rkPnt
[i2
] - extents
[i2
];
395 rfSqrDistance
+= fDelta
*fDelta
;
396 rkPnt
[i2
] = extents
[i2
];
400 static void Case000(Point
& rkPnt
, const Point
& extents
, float& rfSqrDistance
)
404 if(rkPnt
.x
< -extents
.x
)
406 fDelta
= rkPnt
.x
+ extents
.x
;
407 rfSqrDistance
+= fDelta
*fDelta
;
408 rkPnt
.x
= -extents
.x
;
410 else if(rkPnt
.x
> extents
.x
)
412 fDelta
= rkPnt
.x
- extents
.x
;
413 rfSqrDistance
+= fDelta
*fDelta
;
417 if(rkPnt
.y
< -extents
.y
)
419 fDelta
= rkPnt
.y
+ extents
.y
;
420 rfSqrDistance
+= fDelta
*fDelta
;
421 rkPnt
.y
= -extents
.y
;
423 else if(rkPnt
.y
> extents
.y
)
425 fDelta
= rkPnt
.y
- extents
.y
;
426 rfSqrDistance
+= fDelta
*fDelta
;
430 if(rkPnt
.z
< -extents
.z
)
432 fDelta
= rkPnt
.z
+ extents
.z
;
433 rfSqrDistance
+= fDelta
*fDelta
;
434 rkPnt
.z
= -extents
.z
;
436 else if(rkPnt
.z
> extents
.z
)
438 fDelta
= rkPnt
.z
- extents
.z
;
439 rfSqrDistance
+= fDelta
*fDelta
;
444 static float SqrDistance(const Ray
& rkLine
, const Point
& center
, const Point
& extents
, float* pfLParam
)
446 // compute coordinates of line in box coordinate system
447 Point kDiff
= rkLine
.mOrig
- center
;
449 Point kDir
= rkLine
.mDir
;
452 // Apply reflections so that direction vector has nonnegative components.
469 float fSqrDistance
= 0.0f
;
475 if(kDir
.z
>0.0f
) CaseNoZeros(kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (+,+,+)
476 else Case0(0, 1, 2, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (+,+,0)
480 if(kDir
.z
>0.0f
) Case0(0, 2, 1, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (+,0,+)
481 else Case00(0, 1, 2, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (+,0,0)
488 if(kDir
.z
>0.0f
) Case0(1, 2, 0, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (0,+,+)
489 else Case00(1, 0, 2, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (0,+,0)
493 if(kDir
.z
>0.0f
) Case00(2, 0, 1, kPnt
, kDir
, extents
, pfLParam
, fSqrDistance
); // (0,0,+)
496 Case000(kPnt
, extents
, fSqrDistance
); // (0,0,0)
497 if(pfLParam
) *pfLParam
= 0.0f
;
504 inline_
float OPC_SegmentOBBSqrDist(const Segment
& segment
, const Point
& c0
, const Point
& e0
)
507 float fSqrDistance
= SqrDistance(Ray(segment
.GetOrigin(), segment
.ComputeDirection()), c0
, e0
, &fLP
);
510 if(fLP
<=1.0f
) return fSqrDistance
;
511 else return OPC_PointAABBSqrDist(segment
.mP1
, c0
, e0
);
513 else return OPC_PointAABBSqrDist(segment
.mP0
, c0
, e0
);
516 inline_ BOOL
LSSCollider::LSSAABBOverlap(const Point
& center
, const Point
& extents
)
521 float s2
= OPC_SegmentOBBSqrDist(mSeg
, center
, extents
);
522 if(s2
<mRadius2
) return TRUE
;