collision_solver_2d_sat.cpp 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341
  1. /*************************************************************************/
  2. /* collision_solver_2d_sat.cpp */
  3. /*************************************************************************/
  4. /* This file is part of: */
  5. /* GODOT ENGINE */
  6. /* https://godotengine.org */
  7. /*************************************************************************/
  8. /* Copyright (c) 2007-2019 Juan Linietsky, Ariel Manzur. */
  9. /* Copyright (c) 2014-2019 Godot Engine contributors (cf. AUTHORS.md) */
  10. /* */
  11. /* Permission is hereby granted, free of charge, to any person obtaining */
  12. /* a copy of this software and associated documentation files (the */
  13. /* "Software"), to deal in the Software without restriction, including */
  14. /* without limitation the rights to use, copy, modify, merge, publish, */
  15. /* distribute, sublicense, and/or sell copies of the Software, and to */
  16. /* permit persons to whom the Software is furnished to do so, subject to */
  17. /* the following conditions: */
  18. /* */
  19. /* The above copyright notice and this permission notice shall be */
  20. /* included in all copies or substantial portions of the Software. */
  21. /* */
  22. /* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
  23. /* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
  24. /* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.*/
  25. /* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
  26. /* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
  27. /* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
  28. /* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
  29. /*************************************************************************/
  30. #include "collision_solver_2d_sat.h"
  31. #include "core/math/geometry.h"
  32. struct _CollectorCallback2D {
  33. CollisionSolver2DSW::CallbackResult callback;
  34. void *userdata;
  35. bool swap;
  36. bool collided;
  37. Vector2 normal;
  38. Vector2 *sep_axis;
  39. _FORCE_INLINE_ void call(const Vector2 &p_point_A, const Vector2 &p_point_B) {
  40. /*
  41. if (normal.dot(p_point_A) >= normal.dot(p_point_B))
  42. return;
  43. */
  44. if (swap)
  45. callback(p_point_B, p_point_A, userdata);
  46. else
  47. callback(p_point_A, p_point_B, userdata);
  48. }
  49. };
  50. typedef void (*GenerateContactsFunc)(const Vector2 *, int, const Vector2 *, int, _CollectorCallback2D *);
  51. _FORCE_INLINE_ static void _generate_contacts_point_point(const Vector2 *p_points_A, int p_point_count_A, const Vector2 *p_points_B, int p_point_count_B, _CollectorCallback2D *p_collector) {
  52. #ifdef DEBUG_ENABLED
  53. ERR_FAIL_COND(p_point_count_A != 1);
  54. ERR_FAIL_COND(p_point_count_B != 1);
  55. #endif
  56. p_collector->call(*p_points_A, *p_points_B);
  57. }
  58. _FORCE_INLINE_ static void _generate_contacts_point_edge(const Vector2 *p_points_A, int p_point_count_A, const Vector2 *p_points_B, int p_point_count_B, _CollectorCallback2D *p_collector) {
  59. #ifdef DEBUG_ENABLED
  60. ERR_FAIL_COND(p_point_count_A != 1);
  61. ERR_FAIL_COND(p_point_count_B != 2);
  62. #endif
  63. Vector2 closest_B = Geometry::get_closest_point_to_segment_uncapped_2d(*p_points_A, p_points_B);
  64. p_collector->call(*p_points_A, closest_B);
  65. }
  66. struct _generate_contacts_Pair {
  67. bool a;
  68. int idx;
  69. real_t d;
  70. _FORCE_INLINE_ bool operator<(const _generate_contacts_Pair &l) const { return d < l.d; }
  71. };
  72. _FORCE_INLINE_ static void _generate_contacts_edge_edge(const Vector2 *p_points_A, int p_point_count_A, const Vector2 *p_points_B, int p_point_count_B, _CollectorCallback2D *p_collector) {
  73. #ifdef DEBUG_ENABLED
  74. ERR_FAIL_COND(p_point_count_A != 2);
  75. ERR_FAIL_COND(p_point_count_B != 2); // circle is actually a 4x3 matrix
  76. #endif
  77. Vector2 n = p_collector->normal;
  78. Vector2 t = n.tangent();
  79. real_t dA = n.dot(p_points_A[0]);
  80. real_t dB = n.dot(p_points_B[0]);
  81. _generate_contacts_Pair dvec[4];
  82. dvec[0].d = t.dot(p_points_A[0]);
  83. dvec[0].a = true;
  84. dvec[0].idx = 0;
  85. dvec[1].d = t.dot(p_points_A[1]);
  86. dvec[1].a = true;
  87. dvec[1].idx = 1;
  88. dvec[2].d = t.dot(p_points_B[0]);
  89. dvec[2].a = false;
  90. dvec[2].idx = 0;
  91. dvec[3].d = t.dot(p_points_B[1]);
  92. dvec[3].a = false;
  93. dvec[3].idx = 1;
  94. SortArray<_generate_contacts_Pair> sa;
  95. sa.sort(dvec, 4);
  96. for (int i = 1; i <= 2; i++) {
  97. if (dvec[i].a) {
  98. Vector2 a = p_points_A[dvec[i].idx];
  99. Vector2 b = n.plane_project(dB, a);
  100. if (n.dot(a) > n.dot(b) - CMP_EPSILON)
  101. continue;
  102. p_collector->call(a, b);
  103. } else {
  104. Vector2 b = p_points_B[dvec[i].idx];
  105. Vector2 a = n.plane_project(dA, b);
  106. if (n.dot(a) > n.dot(b) - CMP_EPSILON)
  107. continue;
  108. p_collector->call(a, b);
  109. }
  110. }
  111. }
  112. static void _generate_contacts_from_supports(const Vector2 *p_points_A, int p_point_count_A, const Vector2 *p_points_B, int p_point_count_B, _CollectorCallback2D *p_collector) {
  113. #ifdef DEBUG_ENABLED
  114. ERR_FAIL_COND(p_point_count_A < 1);
  115. ERR_FAIL_COND(p_point_count_B < 1);
  116. #endif
  117. static const GenerateContactsFunc generate_contacts_func_table[2][2] = {
  118. {
  119. _generate_contacts_point_point,
  120. _generate_contacts_point_edge,
  121. },
  122. {
  123. 0,
  124. _generate_contacts_edge_edge,
  125. }
  126. };
  127. int pointcount_B;
  128. int pointcount_A;
  129. const Vector2 *points_A;
  130. const Vector2 *points_B;
  131. if (p_point_count_A > p_point_count_B) {
  132. //swap
  133. p_collector->swap = !p_collector->swap;
  134. p_collector->normal = -p_collector->normal;
  135. pointcount_B = p_point_count_A;
  136. pointcount_A = p_point_count_B;
  137. points_A = p_points_B;
  138. points_B = p_points_A;
  139. } else {
  140. pointcount_B = p_point_count_B;
  141. pointcount_A = p_point_count_A;
  142. points_A = p_points_A;
  143. points_B = p_points_B;
  144. }
  145. int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1;
  146. int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1;
  147. GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B];
  148. ERR_FAIL_COND(!contacts_func);
  149. contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_collector);
  150. }
  151. template <class ShapeA, class ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
  152. class SeparatorAxisTest2D {
  153. const ShapeA *shape_A;
  154. const ShapeB *shape_B;
  155. const Transform2D *transform_A;
  156. const Transform2D *transform_B;
  157. real_t best_depth;
  158. Vector2 best_axis;
  159. int best_axis_count;
  160. int best_axis_index;
  161. Vector2 motion_A;
  162. Vector2 motion_B;
  163. real_t margin_A;
  164. real_t margin_B;
  165. _CollectorCallback2D *callback;
  166. public:
  167. _FORCE_INLINE_ bool test_previous_axis() {
  168. if (callback && callback->sep_axis && *callback->sep_axis != Vector2()) {
  169. return test_axis(*callback->sep_axis);
  170. } else {
  171. #ifdef DEBUG_ENABLED
  172. best_axis_count++;
  173. #endif
  174. }
  175. return true;
  176. }
  177. _FORCE_INLINE_ bool test_cast() {
  178. if (castA) {
  179. Vector2 na = motion_A.normalized();
  180. if (!test_axis(na))
  181. return false;
  182. if (!test_axis(na.tangent()))
  183. return false;
  184. }
  185. if (castB) {
  186. Vector2 nb = motion_B.normalized();
  187. if (!test_axis(nb))
  188. return false;
  189. if (!test_axis(nb.tangent()))
  190. return false;
  191. }
  192. return true;
  193. }
  194. _FORCE_INLINE_ bool test_axis(const Vector2 &p_axis) {
  195. Vector2 axis = p_axis;
  196. if (Math::abs(axis.x) < CMP_EPSILON &&
  197. Math::abs(axis.y) < CMP_EPSILON) {
  198. // strange case, try an upwards separator
  199. axis = Vector2(0.0, 1.0);
  200. }
  201. real_t min_A, max_A, min_B, max_B;
  202. if (castA)
  203. shape_A->project_range_cast(motion_A, axis, *transform_A, min_A, max_A);
  204. else
  205. shape_A->project_range(axis, *transform_A, min_A, max_A);
  206. if (castB)
  207. shape_B->project_range_cast(motion_B, axis, *transform_B, min_B, max_B);
  208. else
  209. shape_B->project_range(axis, *transform_B, min_B, max_B);
  210. if (withMargin) {
  211. min_A -= margin_A;
  212. max_A += margin_A;
  213. min_B -= margin_B;
  214. max_B += margin_B;
  215. }
  216. min_B -= (max_A - min_A) * 0.5;
  217. max_B += (max_A - min_A) * 0.5;
  218. real_t dmin = min_B - (min_A + max_A) * 0.5;
  219. real_t dmax = max_B - (min_A + max_A) * 0.5;
  220. if (dmin > 0.0 || dmax < 0.0) {
  221. if (callback && callback->sep_axis)
  222. *callback->sep_axis = axis;
  223. #ifdef DEBUG_ENABLED
  224. best_axis_count++;
  225. #endif
  226. return false; // doesn't contain 0
  227. }
  228. //use the smallest depth
  229. dmin = Math::abs(dmin);
  230. if (dmax < dmin) {
  231. if (dmax < best_depth) {
  232. best_depth = dmax;
  233. best_axis = axis;
  234. #ifdef DEBUG_ENABLED
  235. best_axis_index = best_axis_count;
  236. #endif
  237. }
  238. } else {
  239. if (dmin < best_depth) {
  240. best_depth = dmin;
  241. best_axis = -axis; // keep it as A axis
  242. #ifdef DEBUG_ENABLED
  243. best_axis_index = best_axis_count;
  244. #endif
  245. }
  246. }
  247. #ifdef DEBUG_ENABLED
  248. best_axis_count++;
  249. #endif
  250. return true;
  251. }
  252. _FORCE_INLINE_ void generate_contacts() {
  253. // nothing to do, don't generate
  254. if (best_axis == Vector2(0.0, 0.0))
  255. return;
  256. callback->collided = true;
  257. if (!callback->callback)
  258. return; //only collide, no callback
  259. static const int max_supports = 2;
  260. Vector2 supports_A[max_supports];
  261. int support_count_A;
  262. if (castA) {
  263. shape_A->get_supports_transformed_cast(motion_A, -best_axis, *transform_A, supports_A, support_count_A);
  264. } else {
  265. shape_A->get_supports(transform_A->basis_xform_inv(-best_axis).normalized(), supports_A, support_count_A);
  266. for (int i = 0; i < support_count_A; i++) {
  267. supports_A[i] = transform_A->xform(supports_A[i]);
  268. }
  269. }
  270. if (withMargin) {
  271. for (int i = 0; i < support_count_A; i++) {
  272. supports_A[i] += -best_axis * margin_A;
  273. }
  274. }
  275. Vector2 supports_B[max_supports];
  276. int support_count_B;
  277. if (castB) {
  278. shape_B->get_supports_transformed_cast(motion_B, best_axis, *transform_B, supports_B, support_count_B);
  279. } else {
  280. shape_B->get_supports(transform_B->basis_xform_inv(best_axis).normalized(), supports_B, support_count_B);
  281. for (int i = 0; i < support_count_B; i++) {
  282. supports_B[i] = transform_B->xform(supports_B[i]);
  283. }
  284. }
  285. if (withMargin) {
  286. for (int i = 0; i < support_count_B; i++) {
  287. supports_B[i] += best_axis * margin_B;
  288. }
  289. }
  290. callback->normal = best_axis;
  291. _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);
  292. if (callback && callback->sep_axis && *callback->sep_axis != Vector2())
  293. *callback->sep_axis = Vector2(); //invalidate previous axis (no test)
  294. }
  295. _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A, const Transform2D &p_transform_a, const ShapeB *p_shape_B, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_A = Vector2(), const Vector2 &p_motion_B = Vector2(), real_t p_margin_A = 0, real_t p_margin_B = 0) {
  296. margin_A = p_margin_A;
  297. margin_B = p_margin_B;
  298. best_depth = 1e15;
  299. shape_A = p_shape_A;
  300. shape_B = p_shape_B;
  301. transform_A = &p_transform_a;
  302. transform_B = &p_transform_b;
  303. motion_A = p_motion_A;
  304. motion_B = p_motion_B;
  305. callback = p_collector;
  306. #ifdef DEBUG_ENABLED
  307. best_axis_count = 0;
  308. best_axis_index = -1;
  309. #endif
  310. }
  311. };
  312. /****** SAT TESTS *******/
  313. #define TEST_POINT(m_a, m_b) \
  314. ((!separator.test_axis(((m_a) - (m_b)).normalized())) || \
  315. (castA && !separator.test_axis(((m_a) + p_motion_a - (m_b)).normalized())) || \
  316. (castB && !separator.test_axis(((m_a) - ((m_b) + p_motion_b)).normalized())) || \
  317. (castA && castB && !separator.test_axis(((m_a) + p_motion_a - ((m_b) + p_motion_b)).normalized())))
  318. typedef void (*CollisionFunc)(const Shape2DSW *, const Transform2D &, const Shape2DSW *, const Transform2D &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, real_t, real_t);
  319. template <bool castA, bool castB, bool withMargin>
  320. static void _collision_segment_segment(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  321. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  322. const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW *>(p_b);
  323. SeparatorAxisTest2D<SegmentShape2DSW, SegmentShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, segment_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  324. if (!separator.test_previous_axis())
  325. return;
  326. //this collision is kind of pointless
  327. if (!separator.test_cast())
  328. return;
  329. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  330. return;
  331. if (!separator.test_axis(segment_B->get_xformed_normal(p_transform_b)))
  332. return;
  333. if (withMargin) {
  334. //points grow to circles
  335. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(segment_B->get_a())))
  336. return;
  337. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(segment_B->get_b())))
  338. return;
  339. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(segment_B->get_a())))
  340. return;
  341. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(segment_B->get_b())))
  342. return;
  343. }
  344. separator.generate_contacts();
  345. }
  346. template <bool castA, bool castB, bool withMargin>
  347. static void _collision_segment_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  348. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  349. const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
  350. SeparatorAxisTest2D<SegmentShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  351. if (!separator.test_previous_axis())
  352. return;
  353. if (!separator.test_cast())
  354. return;
  355. //segment normal
  356. if (!separator.test_axis(
  357. (p_transform_a.xform(segment_A->get_b()) - p_transform_a.xform(segment_A->get_a())).normalized().tangent()))
  358. return;
  359. //endpoint a vs circle
  360. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.get_origin()))
  361. return;
  362. //endpoint b vs circle
  363. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.get_origin()))
  364. return;
  365. separator.generate_contacts();
  366. }
  367. template <bool castA, bool castB, bool withMargin>
  368. static void _collision_segment_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  369. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  370. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  371. SeparatorAxisTest2D<SegmentShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  372. if (!separator.test_previous_axis())
  373. return;
  374. if (!separator.test_cast())
  375. return;
  376. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  377. return;
  378. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  379. return;
  380. if (!separator.test_axis(p_transform_b.elements[1].normalized()))
  381. return;
  382. if (withMargin) {
  383. Transform2D inv = p_transform_b.affine_inverse();
  384. Vector2 a = p_transform_a.xform(segment_A->get_a());
  385. Vector2 b = p_transform_a.xform(segment_A->get_b());
  386. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a)))
  387. return;
  388. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b)))
  389. return;
  390. if (castA) {
  391. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a + p_motion_a)))
  392. return;
  393. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b + p_motion_a)))
  394. return;
  395. }
  396. if (castB) {
  397. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b)))
  398. return;
  399. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b - p_motion_b)))
  400. return;
  401. }
  402. if (castA && castB) {
  403. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b + p_motion_a)))
  404. return;
  405. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b - p_motion_b + p_motion_a)))
  406. return;
  407. }
  408. }
  409. separator.generate_contacts();
  410. }
  411. template <bool castA, bool castB, bool withMargin>
  412. static void _collision_segment_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  413. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  414. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  415. SeparatorAxisTest2D<SegmentShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  416. if (!separator.test_previous_axis())
  417. return;
  418. if (!separator.test_cast())
  419. return;
  420. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  421. return;
  422. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  423. return;
  424. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5)))
  425. return;
  426. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5)))
  427. return;
  428. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5)))
  429. return;
  430. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5)))
  431. return;
  432. separator.generate_contacts();
  433. }
  434. template <bool castA, bool castB, bool withMargin>
  435. static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  436. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  437. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  438. SeparatorAxisTest2D<SegmentShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(segment_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  439. if (!separator.test_previous_axis())
  440. return;
  441. if (!separator.test_cast())
  442. return;
  443. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  444. return;
  445. for (int i = 0; i < convex_B->get_point_count(); i++) {
  446. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  447. return;
  448. if (withMargin) {
  449. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(convex_B->get_point(i))))
  450. return;
  451. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(convex_B->get_point(i))))
  452. return;
  453. }
  454. }
  455. separator.generate_contacts();
  456. }
  457. /////////
  458. template <bool castA, bool castB, bool withMargin>
  459. static void _collision_circle_circle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  460. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  461. const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
  462. SeparatorAxisTest2D<CircleShape2DSW, CircleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, circle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  463. if (!separator.test_previous_axis())
  464. return;
  465. if (!separator.test_cast())
  466. return;
  467. if (TEST_POINT(p_transform_a.get_origin(), p_transform_b.get_origin()))
  468. return;
  469. separator.generate_contacts();
  470. }
  471. template <bool castA, bool castB, bool withMargin>
  472. static void _collision_circle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  473. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  474. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  475. SeparatorAxisTest2D<CircleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  476. if (!separator.test_previous_axis())
  477. return;
  478. if (!separator.test_cast())
  479. return;
  480. const Vector2 &sphere = p_transform_a.elements[2];
  481. const Vector2 *axis = &p_transform_b.elements[0];
  482. //const Vector2& half_extents = rectangle_B->get_half_extents();
  483. if (!separator.test_axis(axis[0].normalized()))
  484. return;
  485. if (!separator.test_axis(axis[1].normalized()))
  486. return;
  487. Transform2D binv = p_transform_b.affine_inverse();
  488. {
  489. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphere)))
  490. return;
  491. }
  492. if (castA) {
  493. Vector2 sphereofs = sphere + p_motion_a;
  494. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  495. return;
  496. }
  497. if (castB) {
  498. Vector2 sphereofs = sphere - p_motion_b;
  499. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  500. return;
  501. }
  502. if (castA && castB) {
  503. Vector2 sphereofs = sphere - p_motion_b + p_motion_a;
  504. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  505. return;
  506. }
  507. separator.generate_contacts();
  508. }
  509. template <bool castA, bool castB, bool withMargin>
  510. static void _collision_circle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  511. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  512. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  513. SeparatorAxisTest2D<CircleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  514. if (!separator.test_previous_axis())
  515. return;
  516. if (!separator.test_cast())
  517. return;
  518. //capsule axis
  519. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  520. return;
  521. //capsule endpoints
  522. if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5)))
  523. return;
  524. if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5)))
  525. return;
  526. separator.generate_contacts();
  527. }
  528. template <bool castA, bool castB, bool withMargin>
  529. static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  530. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  531. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  532. SeparatorAxisTest2D<CircleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(circle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  533. if (!separator.test_previous_axis())
  534. return;
  535. if (!separator.test_cast())
  536. return;
  537. //poly faces and poly points vs circle
  538. for (int i = 0; i < convex_B->get_point_count(); i++) {
  539. if (TEST_POINT(p_transform_a.get_origin(), p_transform_b.xform(convex_B->get_point(i))))
  540. return;
  541. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  542. return;
  543. }
  544. separator.generate_contacts();
  545. }
  546. /////////
  547. template <bool castA, bool castB, bool withMargin>
  548. static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  549. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  550. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  551. SeparatorAxisTest2D<RectangleShape2DSW, RectangleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, rectangle_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  552. if (!separator.test_previous_axis())
  553. return;
  554. if (!separator.test_cast())
  555. return;
  556. //box faces A
  557. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  558. return;
  559. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  560. return;
  561. //box faces B
  562. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  563. return;
  564. if (!separator.test_axis(p_transform_b.elements[1].normalized()))
  565. return;
  566. if (withMargin) {
  567. Transform2D invA = p_transform_a.affine_inverse();
  568. Transform2D invB = p_transform_b.affine_inverse();
  569. if (!separator.test_axis(rectangle_A->get_box_axis(p_transform_a, invA, rectangle_B, p_transform_b, invB)))
  570. return;
  571. if (castA || castB) {
  572. Transform2D aofs = p_transform_a;
  573. aofs.elements[2] += p_motion_a;
  574. Transform2D bofs = p_transform_b;
  575. bofs.elements[2] += p_motion_b;
  576. Transform2D aofsinv = aofs.affine_inverse();
  577. Transform2D bofsinv = bofs.affine_inverse();
  578. if (castA) {
  579. if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, p_transform_b, invB)))
  580. return;
  581. }
  582. if (castB) {
  583. if (!separator.test_axis(rectangle_A->get_box_axis(p_transform_a, invA, rectangle_B, bofs, bofsinv)))
  584. return;
  585. }
  586. if (castA && castB) {
  587. if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, bofs, bofsinv)))
  588. return;
  589. }
  590. }
  591. }
  592. separator.generate_contacts();
  593. }
  594. template <bool castA, bool castB, bool withMargin>
  595. static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  596. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  597. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  598. SeparatorAxisTest2D<RectangleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  599. if (!separator.test_previous_axis())
  600. return;
  601. if (!separator.test_cast())
  602. return;
  603. //box faces
  604. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  605. return;
  606. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  607. return;
  608. //capsule axis
  609. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  610. return;
  611. //box endpoints to capsule circles
  612. Transform2D boxinv = p_transform_a.affine_inverse();
  613. for (int i = 0; i < 2; i++) {
  614. {
  615. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  616. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  617. return;
  618. }
  619. if (castA) {
  620. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  621. capsule_endpoint -= p_motion_a;
  622. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  623. return;
  624. }
  625. if (castB) {
  626. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  627. capsule_endpoint += p_motion_b;
  628. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  629. return;
  630. }
  631. if (castA && castB) {
  632. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  633. capsule_endpoint -= p_motion_a;
  634. capsule_endpoint += p_motion_b;
  635. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  636. return;
  637. }
  638. }
  639. separator.generate_contacts();
  640. }
  641. template <bool castA, bool castB, bool withMargin>
  642. static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  643. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  644. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  645. SeparatorAxisTest2D<RectangleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(rectangle_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  646. if (!separator.test_previous_axis())
  647. return;
  648. if (!separator.test_cast())
  649. return;
  650. //box faces
  651. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  652. return;
  653. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  654. return;
  655. //convex faces
  656. Transform2D boxinv;
  657. if (withMargin) {
  658. boxinv = p_transform_a.affine_inverse();
  659. }
  660. for (int i = 0; i < convex_B->get_point_count(); i++) {
  661. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  662. return;
  663. if (withMargin) {
  664. //all points vs all points need to be tested if margin exist
  665. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)))))
  666. return;
  667. if (castA) {
  668. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) - p_motion_a)))
  669. return;
  670. }
  671. if (castB) {
  672. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) + p_motion_b)))
  673. return;
  674. }
  675. if (castA && castB) {
  676. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)) + p_motion_b - p_motion_a)))
  677. return;
  678. }
  679. }
  680. }
  681. separator.generate_contacts();
  682. }
  683. /////////
  684. template <bool castA, bool castB, bool withMargin>
  685. static void _collision_capsule_capsule(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  686. const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
  687. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  688. SeparatorAxisTest2D<CapsuleShape2DSW, CapsuleShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, capsule_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  689. if (!separator.test_previous_axis())
  690. return;
  691. if (!separator.test_cast())
  692. return;
  693. //capsule axis
  694. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  695. return;
  696. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  697. return;
  698. //capsule endpoints
  699. for (int i = 0; i < 2; i++) {
  700. Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (i == 0 ? 0.5 : -0.5);
  701. for (int j = 0; j < 2; j++) {
  702. Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (j == 0 ? 0.5 : -0.5);
  703. if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B))
  704. return;
  705. }
  706. }
  707. separator.generate_contacts();
  708. }
  709. template <bool castA, bool castB, bool withMargin>
  710. static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  711. const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
  712. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  713. SeparatorAxisTest2D<CapsuleShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(capsule_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  714. if (!separator.test_previous_axis())
  715. return;
  716. if (!separator.test_cast())
  717. return;
  718. //capsule axis
  719. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  720. return;
  721. //poly vs capsule
  722. for (int i = 0; i < convex_B->get_point_count(); i++) {
  723. Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));
  724. for (int j = 0; j < 2; j++) {
  725. Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (j == 0 ? 0.5 : -0.5);
  726. if (TEST_POINT(capsule_endpoint_A, cpoint))
  727. return;
  728. }
  729. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  730. return;
  731. }
  732. separator.generate_contacts();
  733. }
  734. /////////
  735. template <bool castA, bool castB, bool withMargin>
  736. static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const Transform2D &p_transform_a, const Shape2DSW *p_b, const Transform2D &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, real_t p_margin_A, real_t p_margin_B) {
  737. const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW *>(p_a);
  738. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  739. SeparatorAxisTest2D<ConvexPolygonShape2DSW, ConvexPolygonShape2DSW, castA, castB, withMargin> separator(convex_A, p_transform_a, convex_B, p_transform_b, p_collector, p_motion_a, p_motion_b, p_margin_A, p_margin_B);
  740. if (!separator.test_previous_axis())
  741. return;
  742. if (!separator.test_cast())
  743. return;
  744. for (int i = 0; i < convex_A->get_point_count(); i++) {
  745. if (!separator.test_axis(convex_A->get_xformed_segment_normal(p_transform_a, i)))
  746. return;
  747. }
  748. for (int i = 0; i < convex_B->get_point_count(); i++) {
  749. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  750. return;
  751. }
  752. if (withMargin) {
  753. for (int i = 0; i < convex_A->get_point_count(); i++) {
  754. for (int j = 0; j < convex_B->get_point_count(); j++) {
  755. if (TEST_POINT(p_transform_a.xform(convex_A->get_point(i)), p_transform_b.xform(convex_B->get_point(j))))
  756. return;
  757. }
  758. }
  759. }
  760. separator.generate_contacts();
  761. }
  762. ////////
  763. bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Transform2D &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Transform2D &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, real_t p_margin_A, real_t p_margin_B) {
  764. Physics2DServer::ShapeType type_A = p_shape_A->get_type();
  765. ERR_FAIL_COND_V(type_A == Physics2DServer::SHAPE_LINE, false);
  766. //ERR_FAIL_COND_V(type_A==Physics2DServer::SHAPE_RAY,false);
  767. ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
  768. Physics2DServer::ShapeType type_B = p_shape_B->get_type();
  769. ERR_FAIL_COND_V(type_B == Physics2DServer::SHAPE_LINE, false);
  770. //ERR_FAIL_COND_V(type_B==Physics2DServer::SHAPE_RAY,false);
  771. ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
  772. static const CollisionFunc collision_table[5][5] = {
  773. { _collision_segment_segment<false, false, false>,
  774. _collision_segment_circle<false, false, false>,
  775. _collision_segment_rectangle<false, false, false>,
  776. _collision_segment_capsule<false, false, false>,
  777. _collision_segment_convex_polygon<false, false, false> },
  778. { 0,
  779. _collision_circle_circle<false, false, false>,
  780. _collision_circle_rectangle<false, false, false>,
  781. _collision_circle_capsule<false, false, false>,
  782. _collision_circle_convex_polygon<false, false, false> },
  783. { 0,
  784. 0,
  785. _collision_rectangle_rectangle<false, false, false>,
  786. _collision_rectangle_capsule<false, false, false>,
  787. _collision_rectangle_convex_polygon<false, false, false> },
  788. { 0,
  789. 0,
  790. 0,
  791. _collision_capsule_capsule<false, false, false>,
  792. _collision_capsule_convex_polygon<false, false, false> },
  793. { 0,
  794. 0,
  795. 0,
  796. 0,
  797. _collision_convex_polygon_convex_polygon<false, false, false> }
  798. };
  799. static const CollisionFunc collision_table_castA[5][5] = {
  800. { _collision_segment_segment<true, false, false>,
  801. _collision_segment_circle<true, false, false>,
  802. _collision_segment_rectangle<true, false, false>,
  803. _collision_segment_capsule<true, false, false>,
  804. _collision_segment_convex_polygon<true, false, false> },
  805. { 0,
  806. _collision_circle_circle<true, false, false>,
  807. _collision_circle_rectangle<true, false, false>,
  808. _collision_circle_capsule<true, false, false>,
  809. _collision_circle_convex_polygon<true, false, false> },
  810. { 0,
  811. 0,
  812. _collision_rectangle_rectangle<true, false, false>,
  813. _collision_rectangle_capsule<true, false, false>,
  814. _collision_rectangle_convex_polygon<true, false, false> },
  815. { 0,
  816. 0,
  817. 0,
  818. _collision_capsule_capsule<true, false, false>,
  819. _collision_capsule_convex_polygon<true, false, false> },
  820. { 0,
  821. 0,
  822. 0,
  823. 0,
  824. _collision_convex_polygon_convex_polygon<true, false, false> }
  825. };
  826. static const CollisionFunc collision_table_castB[5][5] = {
  827. { _collision_segment_segment<false, true, false>,
  828. _collision_segment_circle<false, true, false>,
  829. _collision_segment_rectangle<false, true, false>,
  830. _collision_segment_capsule<false, true, false>,
  831. _collision_segment_convex_polygon<false, true, false> },
  832. { 0,
  833. _collision_circle_circle<false, true, false>,
  834. _collision_circle_rectangle<false, true, false>,
  835. _collision_circle_capsule<false, true, false>,
  836. _collision_circle_convex_polygon<false, true, false> },
  837. { 0,
  838. 0,
  839. _collision_rectangle_rectangle<false, true, false>,
  840. _collision_rectangle_capsule<false, true, false>,
  841. _collision_rectangle_convex_polygon<false, true, false> },
  842. { 0,
  843. 0,
  844. 0,
  845. _collision_capsule_capsule<false, true, false>,
  846. _collision_capsule_convex_polygon<false, true, false> },
  847. { 0,
  848. 0,
  849. 0,
  850. 0,
  851. _collision_convex_polygon_convex_polygon<false, true, false> }
  852. };
  853. static const CollisionFunc collision_table_castA_castB[5][5] = {
  854. { _collision_segment_segment<true, true, false>,
  855. _collision_segment_circle<true, true, false>,
  856. _collision_segment_rectangle<true, true, false>,
  857. _collision_segment_capsule<true, true, false>,
  858. _collision_segment_convex_polygon<true, true, false> },
  859. { 0,
  860. _collision_circle_circle<true, true, false>,
  861. _collision_circle_rectangle<true, true, false>,
  862. _collision_circle_capsule<true, true, false>,
  863. _collision_circle_convex_polygon<true, true, false> },
  864. { 0,
  865. 0,
  866. _collision_rectangle_rectangle<true, true, false>,
  867. _collision_rectangle_capsule<true, true, false>,
  868. _collision_rectangle_convex_polygon<true, true, false> },
  869. { 0,
  870. 0,
  871. 0,
  872. _collision_capsule_capsule<true, true, false>,
  873. _collision_capsule_convex_polygon<true, true, false> },
  874. { 0,
  875. 0,
  876. 0,
  877. 0,
  878. _collision_convex_polygon_convex_polygon<true, true, false> }
  879. };
  880. static const CollisionFunc collision_table_margin[5][5] = {
  881. { _collision_segment_segment<false, false, true>,
  882. _collision_segment_circle<false, false, true>,
  883. _collision_segment_rectangle<false, false, true>,
  884. _collision_segment_capsule<false, false, true>,
  885. _collision_segment_convex_polygon<false, false, true> },
  886. { 0,
  887. _collision_circle_circle<false, false, true>,
  888. _collision_circle_rectangle<false, false, true>,
  889. _collision_circle_capsule<false, false, true>,
  890. _collision_circle_convex_polygon<false, false, true> },
  891. { 0,
  892. 0,
  893. _collision_rectangle_rectangle<false, false, true>,
  894. _collision_rectangle_capsule<false, false, true>,
  895. _collision_rectangle_convex_polygon<false, false, true> },
  896. { 0,
  897. 0,
  898. 0,
  899. _collision_capsule_capsule<false, false, true>,
  900. _collision_capsule_convex_polygon<false, false, true> },
  901. { 0,
  902. 0,
  903. 0,
  904. 0,
  905. _collision_convex_polygon_convex_polygon<false, false, true> }
  906. };
  907. static const CollisionFunc collision_table_castA_margin[5][5] = {
  908. { _collision_segment_segment<true, false, true>,
  909. _collision_segment_circle<true, false, true>,
  910. _collision_segment_rectangle<true, false, true>,
  911. _collision_segment_capsule<true, false, true>,
  912. _collision_segment_convex_polygon<true, false, true> },
  913. { 0,
  914. _collision_circle_circle<true, false, true>,
  915. _collision_circle_rectangle<true, false, true>,
  916. _collision_circle_capsule<true, false, true>,
  917. _collision_circle_convex_polygon<true, false, true> },
  918. { 0,
  919. 0,
  920. _collision_rectangle_rectangle<true, false, true>,
  921. _collision_rectangle_capsule<true, false, true>,
  922. _collision_rectangle_convex_polygon<true, false, true> },
  923. { 0,
  924. 0,
  925. 0,
  926. _collision_capsule_capsule<true, false, true>,
  927. _collision_capsule_convex_polygon<true, false, true> },
  928. { 0,
  929. 0,
  930. 0,
  931. 0,
  932. _collision_convex_polygon_convex_polygon<true, false, true> }
  933. };
  934. static const CollisionFunc collision_table_castB_margin[5][5] = {
  935. { _collision_segment_segment<false, true, true>,
  936. _collision_segment_circle<false, true, true>,
  937. _collision_segment_rectangle<false, true, true>,
  938. _collision_segment_capsule<false, true, true>,
  939. _collision_segment_convex_polygon<false, true, true> },
  940. { 0,
  941. _collision_circle_circle<false, true, true>,
  942. _collision_circle_rectangle<false, true, true>,
  943. _collision_circle_capsule<false, true, true>,
  944. _collision_circle_convex_polygon<false, true, true> },
  945. { 0,
  946. 0,
  947. _collision_rectangle_rectangle<false, true, true>,
  948. _collision_rectangle_capsule<false, true, true>,
  949. _collision_rectangle_convex_polygon<false, true, true> },
  950. { 0,
  951. 0,
  952. 0,
  953. _collision_capsule_capsule<false, true, true>,
  954. _collision_capsule_convex_polygon<false, true, true> },
  955. { 0,
  956. 0,
  957. 0,
  958. 0,
  959. _collision_convex_polygon_convex_polygon<false, true, true> }
  960. };
  961. static const CollisionFunc collision_table_castA_castB_margin[5][5] = {
  962. { _collision_segment_segment<true, true, true>,
  963. _collision_segment_circle<true, true, true>,
  964. _collision_segment_rectangle<true, true, true>,
  965. _collision_segment_capsule<true, true, true>,
  966. _collision_segment_convex_polygon<true, true, true> },
  967. { 0,
  968. _collision_circle_circle<true, true, true>,
  969. _collision_circle_rectangle<true, true, true>,
  970. _collision_circle_capsule<true, true, true>,
  971. _collision_circle_convex_polygon<true, true, true> },
  972. { 0,
  973. 0,
  974. _collision_rectangle_rectangle<true, true, true>,
  975. _collision_rectangle_capsule<true, true, true>,
  976. _collision_rectangle_convex_polygon<true, true, true> },
  977. { 0,
  978. 0,
  979. 0,
  980. _collision_capsule_capsule<true, true, true>,
  981. _collision_capsule_convex_polygon<true, true, true> },
  982. { 0,
  983. 0,
  984. 0,
  985. 0,
  986. _collision_convex_polygon_convex_polygon<true, true, true> }
  987. };
  988. _CollectorCallback2D callback;
  989. callback.callback = p_result_callback;
  990. callback.swap = p_swap;
  991. callback.userdata = p_userdata;
  992. callback.collided = false;
  993. callback.sep_axis = sep_axis;
  994. const Shape2DSW *A = p_shape_A;
  995. const Shape2DSW *B = p_shape_B;
  996. const Transform2D *transform_A = &p_transform_A;
  997. const Transform2D *transform_B = &p_transform_B;
  998. const Vector2 *motion_A = &p_motion_A;
  999. const Vector2 *motion_B = &p_motion_B;
  1000. real_t margin_A = p_margin_A, margin_B = p_margin_B;
  1001. if (type_A > type_B) {
  1002. SWAP(A, B);
  1003. SWAP(transform_A, transform_B);
  1004. SWAP(type_A, type_B);
  1005. SWAP(motion_A, motion_B);
  1006. SWAP(margin_A, margin_B);
  1007. callback.swap = !callback.swap;
  1008. }
  1009. CollisionFunc collision_func;
  1010. if (p_margin_A || p_margin_B) {
  1011. if (*motion_A == Vector2() && *motion_B == Vector2()) {
  1012. collision_func = collision_table_margin[type_A - 2][type_B - 2];
  1013. } else if (*motion_A != Vector2() && *motion_B == Vector2()) {
  1014. collision_func = collision_table_castA_margin[type_A - 2][type_B - 2];
  1015. } else if (*motion_A == Vector2() && *motion_B != Vector2()) {
  1016. collision_func = collision_table_castB_margin[type_A - 2][type_B - 2];
  1017. } else {
  1018. collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2];
  1019. }
  1020. } else {
  1021. if (*motion_A == Vector2() && *motion_B == Vector2()) {
  1022. collision_func = collision_table[type_A - 2][type_B - 2];
  1023. } else if (*motion_A != Vector2() && *motion_B == Vector2()) {
  1024. collision_func = collision_table_castA[type_A - 2][type_B - 2];
  1025. } else if (*motion_A == Vector2() && *motion_B != Vector2()) {
  1026. collision_func = collision_table_castB[type_A - 2][type_B - 2];
  1027. } else {
  1028. collision_func = collision_table_castA_castB[type_A - 2][type_B - 2];
  1029. }
  1030. }
  1031. ERR_FAIL_COND_V(!collision_func, false);
  1032. collision_func(A, *transform_A, B, *transform_B, &callback, *motion_A, *motion_B, margin_A, margin_B);
  1033. return callback.collided;
  1034. }