CollisionAlgorithmsMatrix.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701
  1. #include "anki/collision/CollisionAlgorithmsMatrix.h"
  2. #include "anki/collision/Collision.h"
  3. #include "anki/util/Assert.h"
  4. #include "anki/math/Math.h"
  5. #include <limits>
  6. namespace anki {
  7. //==============================================================================
  8. template<typename T>
  9. bool CollisionAlgorithmsMatrix::tcollide(const CollisionShape& a,
  10. const CollisionShape& b)
  11. {
  12. const T& t = static_cast<const T&>(a);
  13. bool out;
  14. switch(b.getCollisionShapeType())
  15. {
  16. case CollisionShape::CST_LINE_SEG:
  17. out = collide(t, static_cast<const LineSegment&>(b));
  18. case CollisionShape::CST_RAY:
  19. out = collide(t, static_cast<const Ray&>(b));
  20. case CollisionShape::CST_PLANE:
  21. out = collide(t, static_cast<const Plane&>(b));
  22. case CollisionShape::CST_SPHERE:
  23. out = collide(t, static_cast<const Sphere&>(b));
  24. case CollisionShape::CST_AABB:
  25. out = collide(t, static_cast<const Aabb&>(b));
  26. case CollisionShape::CST_OBB:
  27. out = collide(t, static_cast<const Obb&>(b));
  28. case CollisionShape::CST_FRUSTUM:
  29. out = collide(t, static_cast<const Frustum&>(b));
  30. default:
  31. ANKI_ASSERT(0 && "Forgot something");
  32. out = false;
  33. }
  34. return out;
  35. }
  36. //==============================================================================
  37. bool CollisionAlgorithmsMatrix::collide(const CollisionShape& a,
  38. const CollisionShape& b)
  39. {
  40. bool out;
  41. switch(a.getCollisionShapeType())
  42. {
  43. case CollisionShape::CST_LINE_SEG:
  44. out = tcollide<LineSegment>(a, b);
  45. case CollisionShape::CST_RAY:
  46. out = tcollide<Ray>(a, b);
  47. case CollisionShape::CST_PLANE:
  48. out = tcollide<Plane>(a, b);
  49. case CollisionShape::CST_SPHERE:
  50. out = tcollide<Sphere>(a, b);
  51. case CollisionShape::CST_AABB:
  52. out = tcollide<Aabb>(a, b);
  53. case CollisionShape::CST_OBB:
  54. out = tcollide<Obb>(a, b);
  55. case CollisionShape::CST_FRUSTUM:
  56. out = tcollide<Frustum>(a, b);
  57. default:
  58. ANKI_ASSERT(0 && "Forgot something");
  59. out = false;
  60. }
  61. return out;
  62. }
  63. //==============================================================================
  64. // 1st row =
  65. //==============================================================================
  66. //==============================================================================
  67. bool CollisionAlgorithmsMatrix::collide(const Ls& /*a*/, const Ls& /*b*/)
  68. {
  69. ANKI_ASSERT(0 && "N/A");
  70. return false;
  71. }
  72. //==============================================================================
  73. bool CollisionAlgorithmsMatrix::collide(const Ls& ls, const Obb& obb)
  74. {
  75. F32 maxS = std::numeric_limits<F32>::min();
  76. F32 minT = std::numeric_limits<F32>::max();
  77. // compute difference vector
  78. Vec3 diff = obb.getCenter() - ls.getOrigin();
  79. // for each axis do
  80. for(U i = 0; i < 3; ++i)
  81. {
  82. // get axis i
  83. Vec3 axis = obb.getRotation().getColumn(i);
  84. // project relative vector onto axis
  85. F32 e = axis.dot(diff);
  86. F32 f = ls.getDirection().dot(axis);
  87. // ray is parallel to plane
  88. if(Math::isZero(f))
  89. {
  90. // ray passes by box
  91. if(-e - obb.getExtend()[i] > 0.0 || -e + obb.getExtend()[i] > 0.0)
  92. {
  93. return false;
  94. }
  95. continue;
  96. }
  97. F32 s = (e - obb.getExtend()[i]) / f;
  98. F32 t = (e + obb.getExtend()[i]) / f;
  99. // fix order
  100. if(s > t)
  101. {
  102. F32 temp = s;
  103. s = t;
  104. t = temp;
  105. }
  106. // adjust min and max values
  107. if(s > maxS)
  108. {
  109. maxS = s;
  110. }
  111. if(t < minT)
  112. {
  113. minT = t;
  114. }
  115. // check for intersection failure
  116. if(minT < 0.0 || maxS > 1.0 || maxS > minT)
  117. {
  118. return false;
  119. }
  120. }
  121. // done, have intersection
  122. return true;
  123. }
  124. //==============================================================================
  125. bool CollisionAlgorithmsMatrix::collide(const Ls& a, const Frustum& b)
  126. {
  127. return b.insideFrustum(a);
  128. }
  129. //==============================================================================
  130. bool CollisionAlgorithmsMatrix::collide(const Ls& ls, const Plane& p)
  131. {
  132. return ls.testPlane(p) == 0.0;
  133. }
  134. //==============================================================================
  135. bool CollisionAlgorithmsMatrix::collide(const Ls& /*a*/, const Ray& /*b*/)
  136. {
  137. ANKI_ASSERT(0 && "N/A");
  138. return false;
  139. }
  140. //==============================================================================
  141. bool CollisionAlgorithmsMatrix::collide(const Ls& ls, const Sphere& s)
  142. {
  143. const Vec3& v = ls.getDirection();
  144. Vec3 w0 = s.getCenter() - ls.getOrigin();
  145. F32 w0dv = w0.dot(v);
  146. F32 rsq = s.getRadius() * s.getRadius();
  147. if(w0dv < 0.0) // if the ang is >90
  148. {
  149. return w0.getLengthSquared() <= rsq;
  150. }
  151. Vec3 w1 = w0 - v; // aka center - P1, where P1 = seg.origin + seg.dir
  152. F32 w1dv = w1.dot(v);
  153. if(w1dv > 0.0) // if the ang is <90
  154. {
  155. return w1.getLengthSquared() <= rsq;
  156. }
  157. // the big parenthesis is the projection of w0 to v
  158. Vec3 tmp = w0 - (v * (w0.dot(v) / v.getLengthSquared()));
  159. return tmp.getLengthSquared() <= rsq;
  160. }
  161. //==============================================================================
  162. bool CollisionAlgorithmsMatrix::collide(const Ls& ls, const Aabb& aabb)
  163. {
  164. F32 maxS = std::numeric_limits<F32>::min();
  165. F32 minT = std::numeric_limits<F32>::max();
  166. // do tests against three sets of planes
  167. for(U i = 0; i < 3; ++i)
  168. {
  169. // segment is parallel to plane
  170. if(Math::isZero(ls.getDirection()[i]))
  171. {
  172. // segment passes by box
  173. if(ls.getOrigin()[i] < aabb.getMin()[i]
  174. || ls.getOrigin()[i] > aabb.getMax()[i])
  175. {
  176. return false;
  177. }
  178. }
  179. else
  180. {
  181. // compute intersection parameters and sort
  182. F32 s = (aabb.getMin()[i] - ls.getOrigin()[i])
  183. / ls.getDirection()[i];
  184. F32 t = (aabb.getMax()[i] - ls.getOrigin()[i])
  185. / ls.getDirection()[i];
  186. if(s > t)
  187. {
  188. F32 temp = s;
  189. s = t;
  190. t = temp;
  191. }
  192. // adjust min and max values
  193. if(s > maxS)
  194. {
  195. maxS = s;
  196. }
  197. if(t < minT)
  198. {
  199. minT = t;
  200. }
  201. // check for intersection failure
  202. if(minT < 0.0 || maxS > 1.0 || maxS > minT)
  203. {
  204. return false;
  205. }
  206. }
  207. }
  208. // done, have intersection
  209. return true;
  210. }
  211. //==============================================================================
  212. // 2nd row =
  213. //==============================================================================
  214. //==============================================================================
  215. bool CollisionAlgorithmsMatrix::collide(const Obb& o0, const Obb& o1)
  216. {
  217. // extent vectors
  218. const Vec3& a = o0.getExtend();
  219. const Vec3& b = o1.getExtend();
  220. // test factors
  221. F32 cTest, aTest, bTest;
  222. bool parallelAxes = false;
  223. // transpose of rotation of B relative to A, i.e. (R_b^T * R_a)^T
  224. Mat3 rt = o0.getRotation().getTransposed() * o1.getRotation();
  225. // absolute value of relative rotation matrix
  226. Mat3 rabs;
  227. for(U i = 0; i < 3; ++i)
  228. {
  229. for(U j = 0; j < 3; ++j)
  230. {
  231. rabs(i, j) = fabs(rt(i, j));
  232. // if magnitude of dot product between axes is close to one
  233. if(rabs(i, j) + Math::EPSILON >= 1.0)
  234. {
  235. // then box A and box B have near-parallel axes
  236. parallelAxes = true;
  237. }
  238. }
  239. }
  240. // relative translation (in A's frame)
  241. Vec3 c = o0.getRotation().getTransposed()
  242. * (o1.getCenter() - o0.getCenter());
  243. // separating axis A0
  244. cTest = fabs(c.x());
  245. aTest = a.x();
  246. bTest = b.x() * rabs(0, 0) + b.y() * rabs(0, 1) + b.z() * rabs(0, 2);
  247. if(cTest > aTest + bTest)
  248. {
  249. return false;
  250. }
  251. // separating axis A1
  252. cTest = fabs(c.y());
  253. aTest = a.y();
  254. bTest = b.x() * rabs(1, 0) + b.y() * rabs(1, 1) + b.z() * rabs(1, 2);
  255. if(cTest > aTest + bTest)
  256. {
  257. return false;
  258. }
  259. // separating axis A2
  260. cTest = fabs(c.z());
  261. aTest = a.z();
  262. bTest = b.x() * rabs(2, 0) + b.y() * rabs(2, 1) + b.z() * rabs(2, 2);
  263. if(cTest > aTest + bTest)
  264. {
  265. return false;
  266. }
  267. // separating axis B0
  268. cTest = fabs(c.x() * rt(0, 0) + c.y() * rt(1, 0) + c.z() * rt(2, 0));
  269. aTest = a.x() * rabs(0, 0) + a.y() * rabs(1, 0) + a.z() * rabs(2, 0);
  270. bTest = b.x();
  271. if(cTest > aTest + bTest)
  272. {
  273. return false;
  274. }
  275. // separating axis B1
  276. cTest = fabs(c.x() * rt(0, 1) + c.y() * rt(1, 1) + c.z() * rt(2, 1));
  277. aTest = a.x() * rabs(0, 1) + a.y() * rabs(1, 1) + a.z() * rabs(2, 1);
  278. bTest = b.y();
  279. if(cTest > aTest + bTest)
  280. {
  281. return false;
  282. }
  283. // separating axis B2
  284. cTest = fabs(c.x() * rt(0, 2) + c.y() * rt(1, 2) + c.z() * rt(2, 2));
  285. aTest = a.x() * rabs(0, 2) + a.y() * rabs(1, 2) + a.z() * rabs(2, 2);
  286. bTest = b.z();
  287. if(cTest > aTest + bTest)
  288. {
  289. return false;
  290. }
  291. // if the two boxes have parallel axes, we're done, intersection
  292. if(parallelAxes)
  293. {
  294. return true;
  295. }
  296. // separating axis A0 x B0
  297. cTest = fabs(c.z() * rt(1, 0) - c.y() * rt(2, 0));
  298. aTest = a.y() * rabs(2, 0) + a.z() * rabs(1, 0);
  299. bTest = b.y() * rabs(0, 2) + b.z() * rabs(0, 1);
  300. if(cTest > aTest + bTest)
  301. {
  302. return false;
  303. }
  304. // separating axis A0 x B1
  305. cTest = fabs(c.z() * rt(1, 1) - c.y() * rt(2, 1));
  306. aTest = a.y() * rabs(2, 1) + a.z() * rabs(1, 1);
  307. bTest = b.x() * rabs(0, 2) + b.z() * rabs(0, 0);
  308. if(cTest > aTest + bTest)
  309. {
  310. return false;
  311. }
  312. // separating axis A0 x B2
  313. cTest = fabs(c.z() * rt(1, 2) - c.y() * rt(2, 2));
  314. aTest = a.y() * rabs(2, 2) + a.z() * rabs(1, 2);
  315. bTest = b.x() * rabs(0, 1) + b.y() * rabs(0, 0);
  316. if(cTest > aTest + bTest)
  317. {
  318. return false;
  319. }
  320. // separating axis A1 x B0
  321. cTest = fabs(c.x() * rt(2, 0) - c.z() * rt(0, 0));
  322. aTest = a.x() * rabs(2, 0) + a.z() * rabs(0, 0);
  323. bTest = b.y() * rabs(1, 2) + b.z() * rabs(1, 1);
  324. if(cTest > aTest + bTest)
  325. {
  326. return false;
  327. }
  328. // separating axis A1 x B1
  329. cTest = fabs(c.x() * rt(2, 1) - c.z() * rt(0, 1));
  330. aTest = a.x() * rabs(2, 1) + a.z() * rabs(0, 1);
  331. bTest = b.x() * rabs(1, 2) + b.z() * rabs(1, 0);
  332. if(cTest > aTest + bTest)
  333. {
  334. return false;
  335. }
  336. // separating axis A1 x B2
  337. cTest = fabs(c.x() * rt(2, 2) - c.z() * rt(0, 2));
  338. aTest = a.x() * rabs(2, 2) + a.z() * rabs(0, 2);
  339. bTest = b.x() * rabs(1, 1) + b.y() * rabs(1, 0);
  340. if(cTest > aTest + bTest)
  341. {
  342. return false;
  343. }
  344. // separating axis A2 x B0
  345. cTest = fabs(c.y() * rt(0, 0) - c.x() * rt(1, 0));
  346. aTest = a.x() * rabs(1, 0) + a.y() * rabs(0, 0);
  347. bTest = b.y() * rabs(2, 2) + b.z() * rabs(2, 1);
  348. if(cTest > aTest + bTest)
  349. {
  350. return false;
  351. }
  352. // separating axis A2 x B1
  353. cTest = fabs(c.y() * rt(0, 1) - c.x() * rt(1, 1));
  354. aTest = a.x() * rabs(1, 1) + a.y() * rabs(0, 1);
  355. bTest = b.x() * rabs(2, 2) + b.z() * rabs(2, 0);
  356. if(cTest > aTest + bTest)
  357. {
  358. return false;
  359. }
  360. // separating axis A2 x B2
  361. cTest = fabs(c.y() * rt(0, 2) - c.x() * rt(1, 2));
  362. aTest = a.x() * rabs(1, 2) + a.y() * rabs(0, 2);
  363. bTest = b.x() * rabs(2, 1) + b.y() * rabs(2, 0);
  364. if(cTest > aTest + bTest)
  365. {
  366. return false;
  367. }
  368. // all tests failed, have intersection
  369. return true;
  370. }
  371. //==============================================================================
  372. bool CollisionAlgorithmsMatrix::collide(const Obb& a, const Frustum& b)
  373. {
  374. return b.insideFrustum(a);
  375. }
  376. //==============================================================================
  377. bool CollisionAlgorithmsMatrix::collide(const Obb& a, const Plane& b)
  378. {
  379. return a.testPlane(b) == 0.0;
  380. }
  381. //==============================================================================
  382. bool CollisionAlgorithmsMatrix::collide(const Obb& obb, const Ray& r)
  383. {
  384. Aabb aabb_(-obb.getExtend(), obb.getExtend());
  385. Ray newray;
  386. Mat3 rottrans = obb.getRotation().getTransposed();
  387. newray.getOrigin() = rottrans * (r.getOrigin() - obb.getCenter());
  388. newray.getDirection() = rottrans * r.getDirection();
  389. return collide(newray, aabb_);
  390. }
  391. //==============================================================================
  392. bool CollisionAlgorithmsMatrix::collide(const Obb& obb, const Sphere& s)
  393. {
  394. Aabb aabb_(-obb.getExtend(), obb.getExtend()); // aabb_ is in "this" frame
  395. Vec3 newCenter = obb.getRotation().getTransposed()
  396. * (s.getCenter() - obb.getCenter());
  397. Sphere sphere_(newCenter, s.getRadius()); // sphere1 to "this" fame
  398. return collide(sphere_, aabb_);
  399. }
  400. //==============================================================================
  401. bool CollisionAlgorithmsMatrix::collide(const Obb& obb, const Aabb& aabb)
  402. {
  403. Vec3 center_ = (aabb.getMax() + aabb.getMin()) * 0.5;
  404. Vec3 extends_ = (aabb.getMax() - aabb.getMin()) * 0.5;
  405. Obb obb_(center_, Mat3::getIdentity(), extends_);
  406. return collide(obb, obb_);
  407. }
  408. //==============================================================================
  409. // 3rd line (PCS) =
  410. //==============================================================================
  411. //==============================================================================
  412. bool CollisionAlgorithmsMatrix::collide(const Frustum& a, const Frustum& b)
  413. {
  414. return b.insideFrustum(a);
  415. }
  416. //==============================================================================
  417. bool CollisionAlgorithmsMatrix::collide(const Frustum& a, const Plane& b)
  418. {
  419. return a.insideFrustum(b);
  420. }
  421. //==============================================================================
  422. bool CollisionAlgorithmsMatrix::collide(const Frustum& a, const Ray& b)
  423. {
  424. return a.insideFrustum(b);
  425. }
  426. //==============================================================================
  427. bool CollisionAlgorithmsMatrix::collide(const Frustum& a, const Sphere& b)
  428. {
  429. return a.insideFrustum(b);
  430. }
  431. //==============================================================================
  432. bool CollisionAlgorithmsMatrix::collide(const Frustum& a, const Aabb& b)
  433. {
  434. return a.insideFrustum(b);
  435. }
  436. //==============================================================================
  437. // 4th line (P) =
  438. //==============================================================================
  439. //==============================================================================
  440. bool CollisionAlgorithmsMatrix::collide(const Plane& p0, const Plane& p1)
  441. {
  442. return p0.getNormal() != p1.getNormal();
  443. }
  444. //==============================================================================
  445. bool CollisionAlgorithmsMatrix::collide(const Plane& p, const Ray& r)
  446. {
  447. return r.testPlane(p) == 0.0;
  448. }
  449. //==============================================================================
  450. bool CollisionAlgorithmsMatrix::collide(const Plane& p, const Sphere& s)
  451. {
  452. return s.testPlane(p) == 0.0;
  453. }
  454. //==============================================================================
  455. bool CollisionAlgorithmsMatrix::collide(const Plane& p, const Aabb& aabb)
  456. {
  457. return aabb.testPlane(p) == 0.0;
  458. }
  459. //==============================================================================
  460. // 5th line (R) =
  461. //==============================================================================
  462. //==============================================================================
  463. bool CollisionAlgorithmsMatrix::collide(const Ray& a, const Ray& b)
  464. {
  465. ANKI_ASSERT(0 && "N/A");
  466. return false;
  467. }
  468. //==============================================================================
  469. bool CollisionAlgorithmsMatrix::collide(const Ray& r, const Sphere& s)
  470. {
  471. Vec3 w(s.getCenter() - r.getOrigin());
  472. const Vec3& v = r.getDirection();
  473. F32 proj = v.dot(w);
  474. F32 wsq = w.getLengthSquared();
  475. F32 rsq = s.getRadius() * s.getRadius();
  476. if(proj < 0.0 && wsq > rsq)
  477. {
  478. return false;
  479. }
  480. F32 vsq = v.getLengthSquared();
  481. return (vsq * wsq - proj * proj <= vsq * rsq);
  482. }
  483. //==============================================================================
  484. bool CollisionAlgorithmsMatrix::collide(const Ray& r, const Aabb& aabb)
  485. {
  486. F32 maxS = std::numeric_limits<F32>::min();
  487. F32 minT = std::numeric_limits<F32>::max();
  488. // do tests against three sets of planes
  489. for(U i = 0; i < 3; ++i)
  490. {
  491. // ray is parallel to plane
  492. if(Math::isZero(r.getDirection()[i]))
  493. {
  494. // ray passes by box
  495. if(r.getOrigin()[i] < aabb.getMin()[i] ||
  496. r.getOrigin()[i] > aabb.getMax()[i])
  497. {
  498. return false;
  499. }
  500. }
  501. else
  502. {
  503. // compute intersection parameters and sort
  504. F32 s = (aabb.getMin()[i] - r.getOrigin()[i]) /
  505. r.getDirection()[i];
  506. F32 t = (aabb.getMax()[i] - r.getOrigin()[i]) /
  507. r.getDirection()[i];
  508. if(s > t)
  509. {
  510. F32 temp = s;
  511. s = t;
  512. t = temp;
  513. }
  514. // adjust min and max values
  515. if(s > maxS)
  516. {
  517. maxS = s;
  518. }
  519. if(t < minT)
  520. {
  521. minT = t;
  522. }
  523. // check for intersection failure
  524. if(minT < 0.0 || maxS > minT)
  525. {
  526. return false;
  527. }
  528. }
  529. }
  530. // done, have intersection
  531. return true;
  532. }
  533. //==============================================================================
  534. // 6th line (S) =
  535. //==============================================================================
  536. //==============================================================================
  537. bool CollisionAlgorithmsMatrix::collide(const Sphere& a, const Sphere& b)
  538. {
  539. F32 tmp = a.getRadius() + b.getRadius();
  540. return (a.getCenter() - b.getCenter()).getLengthSquared() <= tmp * tmp;
  541. }
  542. //==============================================================================
  543. bool CollisionAlgorithmsMatrix::collide(const Sphere& s, const Aabb& aabb)
  544. {
  545. const Vec3& c = s.getCenter();
  546. // find the box's closest point to the sphere
  547. Vec3 cp; // Closest Point
  548. for(U i = 0; i < 3; i++)
  549. {
  550. // if the center is greater than the max then the closest
  551. // point is the max
  552. if(c[i] > aabb.getMax()[i])
  553. {
  554. cp[i] = aabb.getMax()[i];
  555. }
  556. else if(c[i] < aabb.getMin()[i]) // relative to the above
  557. {
  558. cp[i] = aabb.getMin()[i];
  559. }
  560. else
  561. {
  562. // the c lies between min and max
  563. cp[i] = c[i];
  564. }
  565. }
  566. F32 rsq = s.getRadius() * s.getRadius();
  567. // if the c lies totally inside the box then the sub is the zero,
  568. // this means that the length is also zero and thus its always smaller
  569. // than rsq
  570. Vec3 sub = c - cp;
  571. if(sub.getLengthSquared() <= rsq)
  572. {
  573. return true;
  574. }
  575. return false;
  576. }
  577. //==============================================================================
  578. // 7th line (AABB) =
  579. //==============================================================================
  580. //==============================================================================
  581. bool CollisionAlgorithmsMatrix::collide(const Aabb& a, const Aabb& b)
  582. {
  583. // if separated in x direction
  584. if(a.getMin().x() > b.getMax().x() || b.getMin().x() > a.getMax().x())
  585. {
  586. return false;
  587. }
  588. // if separated in y direction
  589. if(a.getMin().y() > b.getMax().y() || b.getMin().y() > a.getMax().y())
  590. {
  591. return false;
  592. }
  593. // if separated in z direction
  594. if(a.getMin().z() > b.getMax().z() || b.getMin().z() > a.getMax().z())
  595. {
  596. return false;
  597. }
  598. // no separation, must be intersecting
  599. return true;
  600. }
  601. } // end namespace