Intersection.h 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855
  1. /*
  2. Copyright (c) 2013 Daniele Bartolini, Michele Rossi
  3. Copyright (c) 2012 Daniele Bartolini, Simone Boscaratto
  4. Permission is hereby granted, free of charge, to any person
  5. obtaining a copy of this software and associated documentation
  6. files (the "Software"), to deal in the Software without
  7. restriction, including without limitation the rights to use,
  8. copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. copies of the Software, and to permit persons to whom the
  10. Software is furnished to do so, subject to the following
  11. conditions:
  12. The above copyright notice and this permission notice shall be
  13. included in all copies or substantial portions of the Software.
  14. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  15. EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
  16. OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
  17. NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
  18. HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
  19. WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  20. FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  21. OTHER DEALINGS IN THE SOFTWARE.
  22. */
  23. #pragma once
  24. #include "Ray.h"
  25. #include "Plane.h"
  26. #include "Sphere.h"
  27. #include "Frustum.h"
  28. #include "MathUtils.h"
  29. #include "Types.h"
  30. #include "Triangle.h"
  31. #include "Circle.h"
  32. #include "Rect.h"
  33. namespace crown
  34. {
  35. /// Intersection test utils.
  36. /// Table of Intersection tests (3d)
  37. /// +----------+----------+----------+----------+----------+----------+----------+
  38. /// | | Ray | Plane | Sphere | Box | Frustum | Triangle |
  39. /// +----------+----------+----------+----------+----------+----------+----------+
  40. /// | Ray | No | Yes | Yes | No | No | Yes |
  41. /// +----------+----------+----------+----------+----------+----------+----------+
  42. /// | Plane | - | Yes (1) | Yes (+) | No | No | No |
  43. /// +----------+----------+----------+----------+----------+----------+----------+
  44. /// | Sphere | - | - | Yes (+) | No | Yes | Yes (+) |
  45. /// +----------+----------+----------+----------+----------+----------+----------+
  46. /// | Box | - | - | - | Yes (+) | Yes | No |
  47. /// +----------+----------+----------+----------+----------+----------+----------+
  48. /// | Frustum | - | - | - | - | No | No |
  49. /// +----------+----------+----------+----------+----------+----------+----------+
  50. /// | Triangle | - | - | - | - | - | No |
  51. /// +----------+----------+----------+----------+----------+----------+----------+
  52. /// Notes:
  53. /// (1): Intersection of three planes
  54. /// (-): Static intersection only
  55. /// (+): Static/Dynamic intersection
  56. /// Table of Intersection tests (2d)
  57. /// +---------------+----------+-------------+-------------+----------+----------+
  58. /// | | Circle | Rect | O Rect | Segment | Ray 2d |
  59. /// +---------------+----------+-------------+-------------+----------+----------+
  60. /// | Circle | Yes (p-) | No | No | No | No |
  61. /// +---------------+----------+-------------+-------------+----------+----------+
  62. /// | Rect | - | Yes | No | No | No | <- Axis Aligned Rect
  63. /// +---------------+----------+-------------+-------------+----------+----------+
  64. /// | O Rect | - | - | No | No | No | <- Oriented Rect
  65. /// +---------------+----------+-------------+-------------+----------+----------+
  66. /// | Segment | - | - | - | No | No |
  67. /// +---------------+----------+-------------+-------------+----------+----------+
  68. /// | Ray 2d | - | - | - | - | No |
  69. /// +---------------+----------+-------------+-------------+----------+----------+
  70. /// Notes:
  71. /// (p): Penetration vector
  72. /// (-): Static intersection only
  73. /// (+): Static/Dynamic intersection
  74. class Intersection
  75. {
  76. public:
  77. static bool test_ray_plane(const Ray& r, const Plane& p, float& distance, Vector3& inttersectionPoint_t);
  78. static bool test_ray_sphere(const Ray& r, const Sphere& s, float& distance, Vector3& intersectionPoint);
  79. static bool test_ray_box(const Ray& r, const Box& b, float& distance, Vector3& intersectionPoint);
  80. static bool test_ray_triangle(const Ray& r, const Triangle& t, float& distance, Vector3& intersectionPoint);
  81. static bool test_plane_3(const Plane& p1, const Plane& p2, const Plane& p3, Vector3& ip);
  82. static bool test_static_sphere_plane(const Sphere& s, const Plane& p);
  83. static bool test_static_sphere_sphere(const Sphere& a, const Sphere& b);
  84. static bool test_dynamic_sphere_plane(const Sphere& s, const Vector3& d, const Plane& p, float& it, Vector3& intersectionPoint);
  85. static bool test_dynamic_sphere_triangle(const Sphere& s, const Vector3& d, const Triangle& tri, float& it, Vector3& intersectionPoint);
  86. static bool test_dynamic_sphere_sphere(const Sphere& s1, const Vector3& d1, const Sphere& s2, const Vector3& d2, float& it, Vector3& intersectionPoint);
  87. static bool test_static_box_box(const Box& b1, const Box& b2);
  88. static bool test_dynamic_box_box(const Box& b1, const Vector3& v1, const Box& b2, const Vector3& v2, float& it);
  89. static bool test_frustum_sphere(const Frustum& f, const Sphere& s);
  90. static bool test_frustum_box(const Frustum& f, const Box& box);
  91. static bool test_circle_circle(const Circle& c1, const Circle& c2, Vector2& penetration);
  92. static bool test_dynamic_circle_circle(const Circle& c1, const Vector2& d1, const Circle& c2, const Vector2& d2, float& it);
  93. static bool test_rect_rect(const Rect& r1, const Rect& r2, Vector2& penetration);
  94. static bool test_circle_rect(const Circle& c1, const Rect& r2, Vector2& penetration);
  95. private:
  96. // Disable construction
  97. Intersection();
  98. };
  99. //-----------------------------------------------------------------------------
  100. inline bool Intersection::test_ray_plane(const Ray& r, const Plane& p, float& distance, Vector3& intersectionPoint)
  101. {
  102. float nd = r.direction().dot(p.n);
  103. float orpn = r.origin().dot(p.n);
  104. if (nd < 0.0)
  105. {
  106. float dist = (-p.d - orpn) / nd;
  107. if (dist > 0.0)
  108. {
  109. distance = dist;
  110. intersectionPoint = r.origin() + r.direction() * distance;
  111. return true;
  112. }
  113. }
  114. return false;
  115. }
  116. //-----------------------------------------------------------------------------
  117. inline bool Intersection::test_ray_sphere(const Ray& r, const Sphere& s, float& distance, Vector3& intersectionPoint)
  118. {
  119. Vector3 v = s.center() - r.origin();
  120. float b = v.dot(r.direction());
  121. float det = (s.radius() * s.radius()) - v.dot(v) + (b * b);
  122. if (det < 0.0 || b < s.radius())
  123. {
  124. return false;
  125. }
  126. distance = b - math::sqrt(det);
  127. intersectionPoint = r.origin() + r.direction() * distance;
  128. return true;
  129. }
  130. //-----------------------------------------------------------------------------
  131. inline bool Intersection::test_ray_box(const Ray& r, const Box& b, float& /*distance*/, Vector3& /*intersectionPoint*/)
  132. {
  133. if (r.origin().x < b.min().x)
  134. {
  135. if (r.direction().x < 0.0)
  136. {
  137. return false;
  138. }
  139. }
  140. if (r.origin().x > b.max().x)
  141. {
  142. if (r.direction().x > 0.0)
  143. {
  144. return false;
  145. }
  146. }
  147. if (r.origin().y < b.min().y)
  148. {
  149. if (r.direction().y < 0.0)
  150. {
  151. return false;
  152. }
  153. }
  154. if (r.origin().y > b.max().y)
  155. {
  156. if (r.direction().y > 0.0)
  157. {
  158. return false;
  159. }
  160. }
  161. if (r.origin().z < b.min().z)
  162. {
  163. if (r.direction().z < 0.0)
  164. {
  165. return false;
  166. }
  167. }
  168. if (r.origin().z > b.max().z)
  169. {
  170. if (r.direction().z > 0.0)
  171. {
  172. return false;
  173. }
  174. }
  175. // Possibly int32_tersects
  176. return true;
  177. // TODO
  178. }
  179. //-----------------------------------------------------------------------------
  180. inline bool Intersection::test_ray_triangle(const Ray& r, const Triangle& t, float& distance, Vector3& intersectionPoint)
  181. {
  182. if (Intersection::test_ray_plane(r, t.to_plane(), distance, intersectionPoint))
  183. {
  184. if (t.contains_point(intersectionPoint))
  185. {
  186. return true;
  187. }
  188. }
  189. return false;
  190. }
  191. //-----------------------------------------------------------------------------
  192. inline bool Intersection::test_plane_3(const Plane& p1, const Plane& p2, const Plane& p3, Vector3& ip)
  193. {
  194. const Vector3& n1 = p1.n;
  195. const Vector3& n2 = p2.n;
  196. const Vector3& n3 = p3.n;
  197. float den = -n1.cross(n2).dot(n3);
  198. if (math::equals(den, (float)0.0))
  199. {
  200. return false;
  201. }
  202. Vector3 res = p1.d * n2.cross(n3) + p2.d * n3.cross(n1) + p3.d * n1.cross(n2);
  203. ip = res / den;
  204. return true;
  205. }
  206. //-----------------------------------------------------------------------------
  207. inline bool Intersection::test_static_sphere_plane(const Sphere& s, const Plane& p)
  208. {
  209. if (math::abs(p.distance_to_point(s.center())) < s.radius())
  210. {
  211. return true;
  212. }
  213. return false;
  214. }
  215. //-----------------------------------------------------------------------------
  216. inline bool Intersection::test_static_sphere_sphere(const Sphere& a, const Sphere& b)
  217. {
  218. float dist = (b.center() - a.center()).squared_length();
  219. return (dist < (b.radius() + a.radius()) * (b.radius() + a.radius()));
  220. }
  221. //-----------------------------------------------------------------------------
  222. inline bool Intersection::test_dynamic_sphere_plane(const Sphere& s, const Vector3& d, const Plane& p, float& it, Vector3& intersectionPoint)
  223. {
  224. const Vector3& sphereCenter = s.center();
  225. const float sphereRadius = s.radius();
  226. float t0; // Time at which the sphere int32_tersects the plane remaining at the front side of the plane
  227. float t1; // Time at which the sphere int32_tersects the plane remaining at the back side of the plane
  228. float sphereToPlaneDistance = p.distance_to_point(sphereCenter);
  229. float planeNormalDotVelocity = p.n.dot(d);
  230. if (planeNormalDotVelocity > 0.0)
  231. {
  232. return false;
  233. }
  234. // If the sphere is travelling parallel to the plane
  235. if (planeNormalDotVelocity == 0.0)
  236. {
  237. // If the sphere is embedded in the plane
  238. if (math::abs(sphereToPlaneDistance) < sphereRadius)
  239. {
  240. t0 = 0.0;
  241. t1 = 1.0;
  242. it = t0;
  243. intersectionPoint = s.center() - p.n * s.radius();
  244. return true;
  245. }
  246. return false;
  247. }
  248. t0 = (sphereRadius - sphereToPlaneDistance) / planeNormalDotVelocity;
  249. t1 = (-sphereRadius - sphereToPlaneDistance) / planeNormalDotVelocity;
  250. // If _both_ t0 and t1 are outside [0,1] then collision can never happen
  251. if (t0 >= 0.0 && t0 <= 1.0)
  252. {
  253. it = math::min(t0, t1);
  254. intersectionPoint = s.center() - p.n * s.radius() + (d * it);
  255. return true;
  256. }
  257. return false;
  258. }
  259. //-----------------------------------------------------------------------------
  260. inline bool Intersection::test_dynamic_sphere_triangle(const Sphere& s, const Vector3& d, const Triangle& tri, float& it, Vector3& intersectionPoint)
  261. {
  262. Plane triPlane = tri.to_plane();
  263. // Test against the plane containing the triangle
  264. float spherePlaneIt;
  265. if (!test_dynamic_sphere_plane(s, d, triPlane, spherePlaneIt, intersectionPoint))
  266. {
  267. return false;
  268. }
  269. // Check if the int32_tersection point32_t lies inside the triangle
  270. if (tri.contains_point(intersectionPoint))
  271. {
  272. it = spherePlaneIt;
  273. // intersectionPoint is already returned by the above call to test_dynamic_sphere_plane
  274. return true;
  275. }
  276. it = spherePlaneIt;
  277. // Sweep test
  278. // Check for collision against the vertices
  279. bool collisionFound = false;
  280. float a, b, c;
  281. float x1, x2;
  282. // v1
  283. a = d.dot(d);
  284. b = 2.0 * (d.dot(s.center() - tri.m_vertex[0]));
  285. c = (tri.m_vertex[0] - s.center()).dot(tri.m_vertex[0] - s.center()) - (s.radius() * s.radius());
  286. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  287. {
  288. it = math::min(x1, it);
  289. intersectionPoint = tri.m_vertex[0];
  290. collisionFound = true;
  291. }
  292. // v2
  293. b = 2.0 * (d.dot(s.center() - tri.m_vertex[1]));
  294. c = (tri.m_vertex[1] - s.center()).dot(tri.m_vertex[1] - s.center()) - (s.radius() * s.radius());
  295. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  296. {
  297. it = math::min(x1, it);
  298. intersectionPoint = tri.m_vertex[1];
  299. collisionFound = true;
  300. }
  301. // v3
  302. b = 2.0 * (d.dot(s.center() - tri.m_vertex[2]));
  303. c = (tri.m_vertex[2] - s.center()).dot(tri.m_vertex[2] - s.center()) - (s.radius() * s.radius());
  304. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  305. {
  306. it = math::min(x1, it);
  307. intersectionPoint = tri.m_vertex[2];
  308. collisionFound = true;
  309. }
  310. // Check for collisions against the edges
  311. Vector3 edge;
  312. Vector3 centerToVertex;
  313. float edgeDotVelocity;
  314. float edgeDotCenterToVertex;
  315. float edgeSquaredLength;
  316. float velocitySquaredLength;
  317. velocitySquaredLength = d.squared_length();
  318. // e1
  319. edge = tri.m_vertex[1] - tri.m_vertex[0];
  320. centerToVertex = tri.m_vertex[0] - s.center();
  321. edgeDotVelocity = edge.dot(d);
  322. edgeDotCenterToVertex = edge.dot(centerToVertex);
  323. edgeSquaredLength = edge.squared_length();
  324. a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
  325. b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
  326. c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
  327. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  328. {
  329. float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
  330. if (f0 >= 0.0 && f0 <= 1.0)
  331. {
  332. it = math::min(x1, it);
  333. intersectionPoint = tri.m_vertex[0] + f0 * edge;
  334. collisionFound = true;
  335. }
  336. }
  337. // e2
  338. edge = tri.m_vertex[2] - tri.m_vertex[1];
  339. centerToVertex = tri.m_vertex[1] - s.center();
  340. edgeDotVelocity = edge.dot(d);
  341. edgeDotCenterToVertex = edge.dot(centerToVertex);
  342. edgeSquaredLength = edge.squared_length();
  343. a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
  344. b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
  345. c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
  346. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  347. {
  348. float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
  349. if (f0 >= 0.0 && f0 <= 1.0)
  350. {
  351. it = math::min(x1, it);
  352. intersectionPoint = tri.m_vertex[1] + f0 * edge;
  353. collisionFound = true;
  354. }
  355. }
  356. // e3
  357. edge = tri.m_vertex[0] - tri.m_vertex[2];
  358. centerToVertex = tri.m_vertex[2] - s.center();
  359. edgeDotVelocity = edge.dot(d);
  360. edgeDotCenterToVertex = edge.dot(centerToVertex);
  361. edgeSquaredLength = edge.squared_length();
  362. a = edgeSquaredLength * -velocitySquaredLength + edgeDotVelocity * edgeDotVelocity;
  363. b = edgeSquaredLength * (2.0 * d.dot(centerToVertex)) - (2.0 * edgeDotVelocity * edgeDotCenterToVertex);
  364. c = edgeSquaredLength * ((s.radius() * s.radius()) - centerToVertex.squared_length()) + (edgeDotCenterToVertex * edgeDotCenterToVertex);
  365. if (math::solve_quadratic_equation(a, b, c, x1, x2))
  366. {
  367. float f0 = (edgeDotVelocity * x1 - edgeDotCenterToVertex) / edgeSquaredLength;
  368. if (f0 >= 0.0 && f0 <= 1.0)
  369. {
  370. it = math::min(x1, it);
  371. intersectionPoint = tri.m_vertex[2] + f0 * edge;
  372. collisionFound = true;
  373. }
  374. }
  375. return collisionFound;
  376. }
  377. //-----------------------------------------------------------------------------
  378. inline bool Intersection::test_dynamic_sphere_sphere(const Sphere& s1, const Vector3& d1, const Sphere& s2, const Vector3& d2, float& it, Vector3& /*intersectionPoint*/)
  379. {
  380. // s1 == static sphere
  381. // s2 == moving sphere
  382. Vector3 d = d2 - d1;
  383. d.normalize();
  384. const Vector3& cs = s1.center();
  385. const Vector3& cm = s2.center();
  386. Vector3 e = cs - cm;
  387. float r = s1.radius() + s2.radius();
  388. // If ||e|| < r, int32_tersection occurs at t = 0
  389. if (e.length() < r)
  390. {
  391. it = 0.0;
  392. return true;
  393. }
  394. // it == Intersection Time
  395. float ed = e.dot(d);
  396. float squared = (ed * ed) + (r * r) - e.dot(e);
  397. // If the value inside the square root is neg, then no int32_tersection
  398. if (squared < 0.0)
  399. {
  400. return false;
  401. }
  402. float t = ed - math::sqrt(squared);
  403. float l = (d2 - d1).length();
  404. // If t < 0 || t > l, then non int32_tersection in the considered period of time
  405. if (t < 0.0 || t > l)
  406. {
  407. return false;
  408. }
  409. it = t / l;
  410. return true;
  411. }
  412. //-----------------------------------------------------------------------------
  413. inline bool Intersection::test_static_box_box(const Box& b1, const Box& b2)
  414. {
  415. if (b1.min().x > b2.max().x || b1.max().x < b2.min().x)
  416. {
  417. return false;
  418. }
  419. if (b1.min().y > b2.max().y || b1.max().y < b2.min().y)
  420. {
  421. return false;
  422. }
  423. if (b1.min().z > b2.max().z || b1.max().z < b2.min().z)
  424. {
  425. return false;
  426. }
  427. return true;
  428. }
  429. //-----------------------------------------------------------------------------
  430. inline bool Intersection::test_dynamic_box_box(const Box& b1, const Vector3& v1, const Box& b2, const Vector3& v2, float& it)
  431. {
  432. // b1 == static box
  433. // b2 == moving box
  434. Vector3 d = v2 - v1;
  435. // Start time of int32_tersection aint64_t each axis
  436. Vector3 tEnterXYZ(0.0, 0.0, 0.0);
  437. // Stop time of int32_tersection aint64_t each axis
  438. Vector3 tLeaveXYZ(1.0, 1.0, 1.0);
  439. // If the resulting displacement equals zero, then fallback to static int32_tersection test
  440. if (math::equals(d.x, (float)0.0))
  441. {
  442. if (b1.min().x > b2.max().x || b1.max().x < b2.min().x)
  443. {
  444. return false;
  445. }
  446. }
  447. if (math::equals(d.y, (float)0.0))
  448. {
  449. if (b1.min().y > b2.max().y || b1.max().y < b2.min().y)
  450. {
  451. return false;
  452. }
  453. }
  454. if (math::equals(d.z, (float)0.0))
  455. {
  456. if (b1.min().z > b2.max().z || b1.max().z < b2.min().z)
  457. {
  458. return false;
  459. }
  460. }
  461. // Otherwise, compute the enter/leave times aint64_t each axis
  462. float oneOverD = (float)(1.0 / d.x);
  463. tEnterXYZ.x = (b1.min().x - b2.max().x) * oneOverD;
  464. tLeaveXYZ.x = (b1.max().x - b2.min().x) * oneOverD;
  465. oneOverD = (float)(1.0 / d.y);
  466. tEnterXYZ.y = (b1.min().y - b2.max().y) * oneOverD;
  467. tLeaveXYZ.y = (b1.max().y - b2.min().y) * oneOverD;
  468. oneOverD = (float)(1.0 / d.z);
  469. tEnterXYZ.z = (b1.min().z - b2.max().z) * oneOverD;
  470. tLeaveXYZ.z = (b1.max().z - b2.min().z) * oneOverD;
  471. // We must ensure that enter time < leave time
  472. if (tLeaveXYZ.x < tEnterXYZ.x)
  473. {
  474. math::swap(tLeaveXYZ.x, tEnterXYZ.x);
  475. }
  476. if (tLeaveXYZ.y < tEnterXYZ.y)
  477. {
  478. math::swap(tLeaveXYZ.y, tEnterXYZ.y);
  479. }
  480. if (tLeaveXYZ.z < tEnterXYZ.z)
  481. {
  482. math::swap(tLeaveXYZ.z, tEnterXYZ.z);
  483. }
  484. float tEnter = math::max(tEnterXYZ.x, math::max(tEnterXYZ.y, tEnterXYZ.z));
  485. float tLeave = math::min(tLeaveXYZ.x, math::min(tLeaveXYZ.y, tLeaveXYZ.z));
  486. // If tEnter > 1, then there is no int32_tersection in the period
  487. // of time cosidered
  488. if (tEnter > 1.0)
  489. {
  490. return false;
  491. }
  492. it = tEnter;
  493. return tEnter < tLeave;
  494. }
  495. //-----------------------------------------------------------------------------
  496. inline bool Intersection::test_frustum_sphere(const Frustum& f, const Sphere& s)
  497. {
  498. if (f.m_planes[0].distance_to_point(s.center()) < -s.radius() || f.m_planes[1].distance_to_point(s.center()) < -s.radius())
  499. {
  500. return false;
  501. }
  502. if (f.m_planes[2].distance_to_point(s.center()) < -s.radius() || f.m_planes[3].distance_to_point(s.center()) < -s.radius())
  503. {
  504. return false;
  505. }
  506. if (f.m_planes[4].distance_to_point(s.center()) < -s.radius() || f.m_planes[5].distance_to_point(s.center()) < -s.radius())
  507. {
  508. return false;
  509. }
  510. return true;
  511. }
  512. //-----------------------------------------------------------------------------
  513. inline bool Intersection::test_frustum_box(const Frustum& f, const Box& b)
  514. {
  515. uint32_t vertexOutCount;
  516. for (uint32_t i = 0; i < 6; i++)
  517. {
  518. vertexOutCount = 0;
  519. for (uint32_t j = 0; j < 8; j++)
  520. {
  521. if (f.m_planes[i].distance_to_point(b.vertex(j)) < 0.0)
  522. {
  523. vertexOutCount++;
  524. }
  525. }
  526. // If all vertices are outside one face, then the box doesn't int32_tersect the frustum
  527. if (vertexOutCount == 8)
  528. {
  529. return false;
  530. }
  531. }
  532. // If we are here, is because either the box int32_tersects or it is contained in the frustum
  533. return true;
  534. }
  535. //-----------------------------------------------------------------------------
  536. inline bool Intersection::test_circle_circle(const Circle& c1, const Circle& c2, Vector2& penetration)
  537. {
  538. Vector2 distance = c1.center() - c2.center();
  539. float distanceLen2 = distance.squared_length();
  540. float radiusSum = c1.radius() + c2.radius();
  541. if (distanceLen2 > radiusSum*radiusSum)
  542. {
  543. return false;
  544. }
  545. if (distanceLen2 < 0.001)
  546. {
  547. penetration = Vector2(c1.radius(), 0.0);
  548. }
  549. else
  550. {
  551. distanceLen2 = math::sqrt(distanceLen2);
  552. penetration = distance * ((radiusSum - distanceLen2) / distanceLen2);
  553. }
  554. return true;
  555. }
  556. //-----------------------------------------------------------------------------
  557. inline bool Intersection::test_dynamic_circle_circle(const Circle& c1, const Vector2& d1, const Circle& c2, const Vector2& d2, float& it)
  558. {
  559. // c1 == static circle
  560. // c2 == moving circle
  561. Vector2 d = d2 - d1;
  562. d.normalize();
  563. const Vector2& cs = c1.center();
  564. const Vector2& cm = c2.center();
  565. Vector2 e = cs - cm;
  566. float r = c1.radius() + c2.radius();
  567. // If ||e|| < r, int32_tersection occurs at t = 0
  568. if (e.length() < r)
  569. {
  570. it = 0.0;
  571. return true;
  572. }
  573. // it == Intersection Time
  574. float ed = e.dot(d);
  575. float squared = (ed * ed) + (r * r) - e.dot(e);
  576. // If the value inside the square root is neg, then no int32_tersection
  577. if (squared < 0.0)
  578. {
  579. return false;
  580. }
  581. float t = ed - math::sqrt(squared);
  582. float l = (d2 - d1).length();
  583. // If t < 0 || t > l, then non int32_tersection in the considered period of time
  584. if (t < 0.0 || t > l)
  585. {
  586. return false;
  587. }
  588. it = t / l;
  589. return true;
  590. }
  591. //-----------------------------------------------------------------------------
  592. inline bool Intersection::test_rect_rect(const Rect& r1, const Rect& r2, Vector2& penetration)
  593. {
  594. //x
  595. float min1MinusMax2 = r1.min().x - r2.max().x;
  596. float min2MinusMax1 = r2.min().x - r1.max().x;
  597. if (min1MinusMax2 > min2MinusMax1)
  598. {
  599. if (min1MinusMax2 > 0)
  600. {
  601. return false;
  602. }
  603. penetration.x = -min1MinusMax2;
  604. }
  605. else
  606. {
  607. if (min2MinusMax1 > 0)
  608. {
  609. return false;
  610. }
  611. penetration.x = min2MinusMax1;
  612. }
  613. //y
  614. min1MinusMax2 = r1.min().y - r2.max().y;
  615. min2MinusMax1 = r2.min().y - r1.max().y;
  616. if (min1MinusMax2 > min2MinusMax1)
  617. {
  618. if (min1MinusMax2 > 0)
  619. {
  620. return false;
  621. }
  622. penetration.y = -min1MinusMax2;
  623. }
  624. else
  625. {
  626. if (min2MinusMax1 > 0)
  627. {
  628. return false;
  629. }
  630. penetration.y = min2MinusMax1;
  631. }
  632. if (math::abs(penetration.x) < math::abs(penetration.y))
  633. {
  634. penetration.y = 0.0;
  635. }
  636. else
  637. {
  638. penetration.x = 0.0;
  639. }
  640. return true;
  641. }
  642. //-----------------------------------------------------------------------------
  643. inline bool Intersection::test_circle_rect(const Circle& c1, const Rect& r2, Vector2& penetration)
  644. {
  645. bool circleIsAtRight;
  646. if (c1.center().x > (r2.min().x + r2.max().x) / 2)
  647. {
  648. penetration.x = (c1.center().x - c1.radius()) - r2.max().x;
  649. circleIsAtRight = true;
  650. }
  651. else
  652. {
  653. penetration.x = r2.min().x - (c1.center().x + c1.radius());
  654. circleIsAtRight = false;
  655. }
  656. bool circleIsAtTop;
  657. if (c1.center().y > (r2.min().y + r2.max().y) / 2)
  658. {
  659. penetration.y = (c1.center().y - c1.radius()) - r2.max().y;
  660. circleIsAtTop = true;
  661. }
  662. else
  663. {
  664. penetration.y = r2.min().y - (c1.center().y + c1.radius());
  665. circleIsAtTop = false;
  666. }
  667. if (penetration.x < -c1.radius() || penetration.y < -c1.radius())
  668. {
  669. if (penetration.y > 0 || penetration.x > 0)
  670. {
  671. return false;
  672. }
  673. if (penetration.x > penetration.y)
  674. {
  675. penetration.y = 0;
  676. }
  677. else
  678. {
  679. penetration.x = 0;
  680. }
  681. }
  682. //else if (penetration.y < -c1.radius())
  683. //{
  684. // if (penetration.x > 0)
  685. // {
  686. // return false;
  687. // }
  688. // penetration.y = 0;
  689. //}
  690. else
  691. {
  692. penetration += Vector2(c1.radius(), c1.radius());
  693. float len = math::sqrt(penetration.squared_length());
  694. if (len > c1.radius())
  695. {
  696. return false;
  697. }
  698. //The - is to point32_t outwards
  699. penetration *= - (c1.radius() - len) / len;
  700. }
  701. if (circleIsAtRight)
  702. {
  703. penetration.x *= -1;
  704. }
  705. if (circleIsAtTop)
  706. {
  707. penetration.y *= -1;
  708. }
  709. return true;
  710. }
  711. } // namespace crown