collision_solver_2d_sat.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519
  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 "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. //if (normal.dot(p_point_A) >= normal.dot(p_point_B))
  41. // return;
  42. if (swap)
  43. callback(p_point_B, p_point_A, userdata);
  44. else
  45. callback(p_point_A, p_point_B, userdata);
  46. }
  47. };
  48. typedef void (*GenerateContactsFunc)(const Vector2 *, int, const Vector2 *, int, _CollectorCallback2D *);
  49. _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) {
  50. #ifdef DEBUG_ENABLED
  51. ERR_FAIL_COND(p_point_count_A != 1);
  52. ERR_FAIL_COND(p_point_count_B != 1);
  53. #endif
  54. p_collector->call(*p_points_A, *p_points_B);
  55. }
  56. _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) {
  57. #ifdef DEBUG_ENABLED
  58. ERR_FAIL_COND(p_point_count_A != 1);
  59. ERR_FAIL_COND(p_point_count_B != 2);
  60. #endif
  61. Vector2 closest_B = Geometry::get_closest_point_to_segment_uncapped_2d(*p_points_A, p_points_B);
  62. p_collector->call(*p_points_A, closest_B);
  63. }
  64. struct _generate_contacts_Pair {
  65. bool a;
  66. int idx;
  67. float d;
  68. _FORCE_INLINE_ bool operator<(const _generate_contacts_Pair &l) const { return d < l.d; }
  69. };
  70. _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) {
  71. #ifdef DEBUG_ENABLED
  72. ERR_FAIL_COND(p_point_count_A != 2);
  73. ERR_FAIL_COND(p_point_count_B != 2); // circle is actually a 4x3 matrix
  74. #endif
  75. #if 0
  76. Vector2 rel_A=p_points_A[1]-p_points_A[0];
  77. Vector2 rel_B=p_points_B[1]-p_points_B[0];
  78. Vector2 t = p_collector->normal.tangent();
  79. print_line("tangent: "+t);
  80. real_t dA[2]={t.dot(p_points_A[0]),t.dot(p_points_A[1])};
  81. Vector2 pA[2]={p_points_A[0],p_points_A[1]};
  82. if (dA[0]>dA[1]) {
  83. SWAP(dA[0],dA[1]);
  84. SWAP(pA[0],pA[1]);
  85. }
  86. float dB[2]={t.dot(p_points_B[0]),t.dot(p_points_B[1])};
  87. Vector2 pB[2]={p_points_B[0],p_points_B[1]};
  88. if (dB[0]>dB[1]) {
  89. SWAP(dB[0],dB[1]);
  90. SWAP(pB[0],pB[1]);
  91. }
  92. if (dA[0]<dB[0]) {
  93. Vector2 n = (p_points_A[1]-p_points_A[0]).normalized().tangent();
  94. real_t d = n.dot(p_points_A[1]);
  95. if (dA[1]>dB[1]) {
  96. //A contains B
  97. for(int i=0;i<2;i++) {
  98. Vector2 b = p_points_B[i];
  99. Vector2 a = n.plane_project(d,b);
  100. if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-CMP_EPSILON)
  101. continue;
  102. p_collector->call(a,b);
  103. }
  104. } else {
  105. // B0,A1 containment
  106. Vector2 n_B = (p_points_B[1]-p_points_B[0]).normalized().tangent();
  107. real_t d_B = n_B.dot(p_points_B[1]);
  108. // first, B on A
  109. {
  110. Vector2 b = p_points_B[0];
  111. Vector2 a = n.plane_project(d,b);
  112. if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON)
  113. p_collector->call(a,b);
  114. }
  115. // second, A on B
  116. {
  117. Vector2 a = p_points_A[1];
  118. Vector2 b = n_B.plane_project(d_B,a);
  119. if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON)
  120. p_collector->call(a,b);
  121. }
  122. }
  123. } else {
  124. Vector2 n = (p_points_B[1]-p_points_B[0]).normalized().tangent();
  125. real_t d = n.dot(p_points_B[1]);
  126. if (dB[1]>dA[1]) {
  127. //B contains A
  128. for(int i=0;i<2;i++) {
  129. Vector2 a = p_points_A[i];
  130. Vector2 b = n.plane_project(d,a);
  131. if (p_collector->normal.dot(a) > p_collector->normal.dot(b)-CMP_EPSILON)
  132. continue;
  133. p_collector->call(a,b);
  134. }
  135. } else {
  136. // A0,B1 containment
  137. Vector2 n_A = (p_points_A[1]-p_points_A[0]).normalized().tangent();
  138. real_t d_A = n_A.dot(p_points_A[1]);
  139. // first A on B
  140. {
  141. Vector2 a = p_points_A[0];
  142. Vector2 b = n.plane_project(d,a);
  143. if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON)
  144. p_collector->call(a,b);
  145. }
  146. //second, B on A
  147. {
  148. Vector2 b = p_points_B[1];
  149. Vector2 a = n_A.plane_project(d_A,b);
  150. if (p_collector->normal.dot(a) < p_collector->normal.dot(b)-CMP_EPSILON)
  151. p_collector->call(a,b);
  152. }
  153. }
  154. }
  155. #endif
  156. #if 1
  157. Vector2 n = p_collector->normal;
  158. Vector2 t = n.tangent();
  159. real_t dA = n.dot(p_points_A[0]);
  160. real_t dB = n.dot(p_points_B[0]);
  161. _generate_contacts_Pair dvec[4];
  162. dvec[0].d = t.dot(p_points_A[0]);
  163. dvec[0].a = true;
  164. dvec[0].idx = 0;
  165. dvec[1].d = t.dot(p_points_A[1]);
  166. dvec[1].a = true;
  167. dvec[1].idx = 1;
  168. dvec[2].d = t.dot(p_points_B[0]);
  169. dvec[2].a = false;
  170. dvec[2].idx = 0;
  171. dvec[3].d = t.dot(p_points_B[1]);
  172. dvec[3].a = false;
  173. dvec[3].idx = 1;
  174. SortArray<_generate_contacts_Pair> sa;
  175. sa.sort(dvec, 4);
  176. for (int i = 1; i <= 2; i++) {
  177. if (dvec[i].a) {
  178. Vector2 a = p_points_A[dvec[i].idx];
  179. Vector2 b = n.plane_project(dB, a);
  180. if (n.dot(a) > n.dot(b) - CMP_EPSILON)
  181. continue;
  182. p_collector->call(a, b);
  183. } else {
  184. Vector2 b = p_points_B[dvec[i].idx];
  185. Vector2 a = n.plane_project(dA, b);
  186. if (n.dot(a) > n.dot(b) - CMP_EPSILON)
  187. continue;
  188. p_collector->call(a, b);
  189. }
  190. }
  191. #elif 0
  192. Vector2 axis = rel_A.normalized(); //make an axis
  193. Vector2 axis_B = rel_B.normalized();
  194. if (axis.dot(axis_B) < 0)
  195. axis_B = -axis_B;
  196. axis = (axis + axis_B) * 0.5;
  197. Vector2 base_A = p_points_A[0] - axis * axis.dot(p_points_A[0]);
  198. Vector2 base_B = p_points_B[0] - axis * axis.dot(p_points_B[0]);
  199. //sort all 4 points in axis
  200. float dvec[4] = { axis.dot(p_points_A[0]), axis.dot(p_points_A[1]), axis.dot(p_points_B[0]), axis.dot(p_points_B[1]) };
  201. //todo , find max/min and then use 2 central points
  202. SortArray<float> sa;
  203. sa.sort(dvec, 4);
  204. //use the middle ones as contacts
  205. for (int i = 1; i <= 2; i++) {
  206. Vector2 a = base_A + axis * dvec[i];
  207. Vector2 b = base_B + axis * dvec[i];
  208. if (p_collector->normal.dot(a) > p_collector->normal.dot(b) - 0.01) {
  209. print_line("fail a: " + a);
  210. print_line("fail b: " + b);
  211. continue;
  212. }
  213. print_line("res a: " + a);
  214. print_line("res b: " + b);
  215. p_collector->call(a, b);
  216. }
  217. #endif
  218. }
  219. 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) {
  220. #ifdef DEBUG_ENABLED
  221. ERR_FAIL_COND(p_point_count_A < 1);
  222. ERR_FAIL_COND(p_point_count_B < 1);
  223. #endif
  224. static const GenerateContactsFunc generate_contacts_func_table[2][2] = {
  225. {
  226. _generate_contacts_point_point,
  227. _generate_contacts_point_edge,
  228. },
  229. {
  230. 0,
  231. _generate_contacts_edge_edge,
  232. }
  233. };
  234. int pointcount_B;
  235. int pointcount_A;
  236. const Vector2 *points_A;
  237. const Vector2 *points_B;
  238. if (p_point_count_A > p_point_count_B) {
  239. //swap
  240. p_collector->swap = !p_collector->swap;
  241. p_collector->normal = -p_collector->normal;
  242. pointcount_B = p_point_count_A;
  243. pointcount_A = p_point_count_B;
  244. points_A = p_points_B;
  245. points_B = p_points_A;
  246. } else {
  247. pointcount_B = p_point_count_B;
  248. pointcount_A = p_point_count_A;
  249. points_A = p_points_A;
  250. points_B = p_points_B;
  251. }
  252. int version_A = (pointcount_A > 3 ? 3 : pointcount_A) - 1;
  253. int version_B = (pointcount_B > 3 ? 3 : pointcount_B) - 1;
  254. GenerateContactsFunc contacts_func = generate_contacts_func_table[version_A][version_B];
  255. ERR_FAIL_COND(!contacts_func);
  256. contacts_func(points_A, pointcount_A, points_B, pointcount_B, p_collector);
  257. }
  258. template <class ShapeA, class ShapeB, bool castA = false, bool castB = false, bool withMargin = false>
  259. class SeparatorAxisTest2D {
  260. const ShapeA *shape_A;
  261. const ShapeB *shape_B;
  262. const Matrix32 *transform_A;
  263. const Matrix32 *transform_B;
  264. real_t best_depth;
  265. Vector2 best_axis;
  266. int best_axis_count;
  267. int best_axis_index;
  268. Vector2 motion_A;
  269. Vector2 motion_B;
  270. real_t margin_A;
  271. real_t margin_B;
  272. _CollectorCallback2D *callback;
  273. public:
  274. _FORCE_INLINE_ bool test_previous_axis() {
  275. if (callback && callback->sep_axis && *callback->sep_axis != Vector2()) {
  276. return test_axis(*callback->sep_axis);
  277. } else {
  278. #ifdef DEBUG_ENABLED
  279. best_axis_count++;
  280. #endif
  281. }
  282. return true;
  283. }
  284. _FORCE_INLINE_ bool test_cast() {
  285. if (castA) {
  286. Vector2 na = motion_A.normalized();
  287. if (!test_axis(na))
  288. return false;
  289. if (!test_axis(na.tangent()))
  290. return false;
  291. }
  292. if (castB) {
  293. Vector2 nb = motion_B.normalized();
  294. if (!test_axis(nb))
  295. return false;
  296. if (!test_axis(nb.tangent()))
  297. return false;
  298. }
  299. return true;
  300. }
  301. _FORCE_INLINE_ bool test_axis(const Vector2 &p_axis) {
  302. Vector2 axis = p_axis;
  303. if (Math::abs(axis.x) < CMP_EPSILON &&
  304. Math::abs(axis.y) < CMP_EPSILON) {
  305. // strange case, try an upwards separator
  306. axis = Vector2(0.0, 1.0);
  307. }
  308. real_t min_A, max_A, min_B, max_B;
  309. if (castA)
  310. shape_A->project_range_cast(motion_A, axis, *transform_A, min_A, max_A);
  311. else
  312. shape_A->project_range(axis, *transform_A, min_A, max_A);
  313. if (castB)
  314. shape_B->project_range_cast(motion_B, axis, *transform_B, min_B, max_B);
  315. else
  316. shape_B->project_range(axis, *transform_B, min_B, max_B);
  317. if (withMargin) {
  318. min_A -= margin_A;
  319. max_A += margin_A;
  320. min_B -= margin_B;
  321. max_B += margin_B;
  322. }
  323. min_B -= (max_A - min_A) * 0.5;
  324. max_B += (max_A - min_A) * 0.5;
  325. real_t dmin = min_B - (min_A + max_A) * 0.5;
  326. real_t dmax = max_B - (min_A + max_A) * 0.5;
  327. if (dmin > 0.0 || dmax < 0.0) {
  328. if (callback && callback->sep_axis)
  329. *callback->sep_axis = axis;
  330. #ifdef DEBUG_ENABLED
  331. best_axis_count++;
  332. #endif
  333. return false; // doesn't contain 0
  334. }
  335. //use the smallest depth
  336. dmin = Math::abs(dmin);
  337. if (dmax < dmin) {
  338. if (dmax < best_depth) {
  339. best_depth = dmax;
  340. best_axis = axis;
  341. #ifdef DEBUG_ENABLED
  342. best_axis_index = best_axis_count;
  343. #endif
  344. }
  345. } else {
  346. if (dmin < best_depth) {
  347. best_depth = dmin;
  348. best_axis = -axis; // keep it as A axis
  349. #ifdef DEBUG_ENABLED
  350. best_axis_index = best_axis_count;
  351. #endif
  352. }
  353. }
  354. // print_line("test axis: "+p_axis+" depth: "+rtos(best_depth));
  355. #ifdef DEBUG_ENABLED
  356. best_axis_count++;
  357. #endif
  358. return true;
  359. }
  360. _FORCE_INLINE_ void generate_contacts() {
  361. // nothing to do, don't generate
  362. if (best_axis == Vector2(0.0, 0.0))
  363. return;
  364. callback->collided = true;
  365. if (!callback->callback)
  366. return; //only collide, no callback
  367. static const int max_supports = 2;
  368. Vector2 supports_A[max_supports];
  369. int support_count_A;
  370. if (castA) {
  371. shape_A->get_supports_transformed_cast(motion_A, -best_axis, *transform_A, supports_A, support_count_A);
  372. } else {
  373. shape_A->get_supports(transform_A->basis_xform_inv(-best_axis).normalized(), supports_A, support_count_A);
  374. for (int i = 0; i < support_count_A; i++) {
  375. supports_A[i] = transform_A->xform(supports_A[i]);
  376. }
  377. }
  378. if (withMargin) {
  379. for (int i = 0; i < support_count_A; i++) {
  380. supports_A[i] += -best_axis * margin_A;
  381. }
  382. }
  383. Vector2 supports_B[max_supports];
  384. int support_count_B;
  385. if (castB) {
  386. shape_B->get_supports_transformed_cast(motion_B, best_axis, *transform_B, supports_B, support_count_B);
  387. } else {
  388. shape_B->get_supports(transform_B->basis_xform_inv(best_axis).normalized(), supports_B, support_count_B);
  389. for (int i = 0; i < support_count_B; i++) {
  390. supports_B[i] = transform_B->xform(supports_B[i]);
  391. }
  392. }
  393. if (withMargin) {
  394. for (int i = 0; i < support_count_B; i++) {
  395. supports_B[i] += best_axis * margin_B;
  396. }
  397. }
  398. /*
  399. print_line("**************************");
  400. printf("CBK: %p\n",callback->userdata);
  401. print_line("type A: "+itos(shape_A->get_type()));
  402. print_line("type B: "+itos(shape_B->get_type()));
  403. print_line("xform A: "+*transform_A);
  404. print_line("xform B: "+*transform_B);
  405. print_line("normal: "+best_axis);
  406. print_line("depth: "+rtos(best_depth));
  407. print_line("index: "+itos(best_axis_index));
  408. for(int i=0;i<support_count_A;i++) {
  409. print_line("A-"+itos(i)+": "+supports_A[i]);
  410. }
  411. for(int i=0;i<support_count_B;i++) {
  412. print_line("B-"+itos(i)+": "+supports_B[i]);
  413. }
  414. //*/
  415. callback->normal = best_axis;
  416. _generate_contacts_from_supports(supports_A, support_count_A, supports_B, support_count_B, callback);
  417. if (callback && callback->sep_axis && *callback->sep_axis != Vector2())
  418. *callback->sep_axis = Vector2(); //invalidate previous axis (no test)
  419. //CollisionSolver2DSW::CallbackResult cbk=NULL;
  420. //cbk(Vector2(),Vector2(),NULL);
  421. }
  422. _FORCE_INLINE_ SeparatorAxisTest2D(const ShapeA *p_shape_A, const Matrix32 &p_transform_a, const ShapeB *p_shape_B, const Matrix32 &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) {
  423. margin_A = p_margin_A;
  424. margin_B = p_margin_B;
  425. best_depth = 1e15;
  426. shape_A = p_shape_A;
  427. shape_B = p_shape_B;
  428. transform_A = &p_transform_a;
  429. transform_B = &p_transform_b;
  430. motion_A = p_motion_A;
  431. motion_B = p_motion_B;
  432. callback = p_collector;
  433. #ifdef DEBUG_ENABLED
  434. best_axis_count = 0;
  435. best_axis_index = -1;
  436. #endif
  437. }
  438. };
  439. /****** SAT TESTS *******/
  440. /****** SAT TESTS *******/
  441. /****** SAT TESTS *******/
  442. /****** SAT TESTS *******/
  443. #define TEST_POINT(m_a, m_b) \
  444. ((!separator.test_axis(((m_a) - (m_b)).normalized())) || \
  445. (castA && !separator.test_axis(((m_a) + p_motion_a - (m_b)).normalized())) || \
  446. (castB && !separator.test_axis(((m_a) - ((m_b) + p_motion_b)).normalized())) || \
  447. (castA && castB && !separator.test_axis(((m_a) + p_motion_a - ((m_b) + p_motion_b)).normalized())))
  448. typedef void (*CollisionFunc)(const Shape2DSW *, const Matrix32 &, const Shape2DSW *, const Matrix32 &, _CollectorCallback2D *p_collector, const Vector2 &, const Vector2 &, float, float);
  449. template <bool castA, bool castB, bool withMargin>
  450. static void _collision_segment_segment(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  451. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  452. const SegmentShape2DSW *segment_B = static_cast<const SegmentShape2DSW *>(p_b);
  453. 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);
  454. if (!separator.test_previous_axis())
  455. return;
  456. //this collision is kind of pointless
  457. //if (!separator.test_previous_axis())
  458. // return;
  459. if (!separator.test_cast())
  460. return;
  461. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  462. return;
  463. if (!separator.test_axis(segment_B->get_xformed_normal(p_transform_b)))
  464. return;
  465. if (withMargin) {
  466. //points grow to circles
  467. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(segment_B->get_a())))
  468. return;
  469. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(segment_B->get_b())))
  470. return;
  471. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(segment_B->get_a())))
  472. return;
  473. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(segment_B->get_b())))
  474. return;
  475. }
  476. separator.generate_contacts();
  477. }
  478. template <bool castA, bool castB, bool withMargin>
  479. static void _collision_segment_circle(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  480. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  481. const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
  482. 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);
  483. if (!separator.test_previous_axis())
  484. return;
  485. if (!separator.test_cast())
  486. return;
  487. //segment normal
  488. if (!separator.test_axis(
  489. (p_transform_a.xform(segment_A->get_b()) - p_transform_a.xform(segment_A->get_a())).normalized().tangent()))
  490. return;
  491. //endpoint a vs circle
  492. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.get_origin()))
  493. return;
  494. //endpoint b vs circle
  495. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.get_origin()))
  496. return;
  497. separator.generate_contacts();
  498. }
  499. template <bool castA, bool castB, bool withMargin>
  500. static void _collision_segment_rectangle(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  501. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  502. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  503. 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);
  504. if (!separator.test_previous_axis())
  505. return;
  506. if (!separator.test_cast())
  507. return;
  508. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  509. return;
  510. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  511. return;
  512. if (!separator.test_axis(p_transform_b.elements[1].normalized()))
  513. return;
  514. if (withMargin) {
  515. Matrix32 inv = p_transform_b.affine_inverse();
  516. Vector2 a = p_transform_a.xform(segment_A->get_a());
  517. Vector2 b = p_transform_a.xform(segment_A->get_b());
  518. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a)))
  519. return;
  520. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b)))
  521. return;
  522. if (castA) {
  523. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a + p_motion_a)))
  524. return;
  525. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b + p_motion_a)))
  526. return;
  527. }
  528. if (castB) {
  529. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b)))
  530. return;
  531. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b - p_motion_b)))
  532. return;
  533. }
  534. if (castA && castB) {
  535. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, a - p_motion_b + p_motion_a)))
  536. return;
  537. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, inv, b - p_motion_b + p_motion_a)))
  538. return;
  539. }
  540. }
  541. separator.generate_contacts();
  542. }
  543. template <bool castA, bool castB, bool withMargin>
  544. static void _collision_segment_capsule(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  545. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  546. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  547. 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);
  548. if (!separator.test_previous_axis())
  549. return;
  550. if (!separator.test_cast())
  551. return;
  552. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  553. return;
  554. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  555. return;
  556. 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)))
  557. return;
  558. 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)))
  559. return;
  560. 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)))
  561. return;
  562. 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)))
  563. return;
  564. separator.generate_contacts();
  565. }
  566. template <bool castA, bool castB, bool withMargin>
  567. static void _collision_segment_convex_polygon(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  568. const SegmentShape2DSW *segment_A = static_cast<const SegmentShape2DSW *>(p_a);
  569. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  570. 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);
  571. if (!separator.test_previous_axis())
  572. return;
  573. if (!separator.test_cast())
  574. return;
  575. if (!separator.test_axis(segment_A->get_xformed_normal(p_transform_a)))
  576. return;
  577. for (int i = 0; i < convex_B->get_point_count(); i++) {
  578. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  579. return;
  580. if (withMargin) {
  581. if (TEST_POINT(p_transform_a.xform(segment_A->get_a()), p_transform_b.xform(convex_B->get_point(i))))
  582. return;
  583. if (TEST_POINT(p_transform_a.xform(segment_A->get_b()), p_transform_b.xform(convex_B->get_point(i))))
  584. return;
  585. }
  586. }
  587. separator.generate_contacts();
  588. }
  589. /////////
  590. template <bool castA, bool castB, bool withMargin>
  591. static void _collision_circle_circle(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  592. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  593. const CircleShape2DSW *circle_B = static_cast<const CircleShape2DSW *>(p_b);
  594. 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);
  595. if (!separator.test_previous_axis())
  596. return;
  597. if (!separator.test_cast())
  598. return;
  599. if (TEST_POINT(p_transform_a.get_origin(), p_transform_b.get_origin()))
  600. return;
  601. separator.generate_contacts();
  602. }
  603. template <bool castA, bool castB, bool withMargin>
  604. static void _collision_circle_rectangle(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  605. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  606. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  607. 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);
  608. if (!separator.test_previous_axis())
  609. return;
  610. if (!separator.test_cast())
  611. return;
  612. const Vector2 &sphere = p_transform_a.elements[2];
  613. const Vector2 *axis = &p_transform_b.elements[0];
  614. // const Vector2& half_extents = rectangle_B->get_half_extents();
  615. if (!separator.test_axis(axis[0].normalized()))
  616. return;
  617. if (!separator.test_axis(axis[1].normalized()))
  618. return;
  619. Matrix32 binv = p_transform_b.affine_inverse();
  620. {
  621. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphere)))
  622. return;
  623. }
  624. if (castA) {
  625. Vector2 sphereofs = sphere + p_motion_a;
  626. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  627. return;
  628. }
  629. if (castB) {
  630. Vector2 sphereofs = sphere - p_motion_b;
  631. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  632. return;
  633. }
  634. if (castA && castB) {
  635. Vector2 sphereofs = sphere - p_motion_b + p_motion_a;
  636. if (!separator.test_axis(rectangle_B->get_circle_axis(p_transform_b, binv, sphereofs)))
  637. return;
  638. }
  639. separator.generate_contacts();
  640. }
  641. template <bool castA, bool castB, bool withMargin>
  642. static void _collision_circle_capsule(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  643. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  644. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  645. 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);
  646. if (!separator.test_previous_axis())
  647. return;
  648. if (!separator.test_cast())
  649. return;
  650. //capsule axis
  651. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  652. return;
  653. //capsule endpoints
  654. if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * 0.5)))
  655. return;
  656. if (TEST_POINT(p_transform_a.get_origin(), (p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * -0.5)))
  657. return;
  658. separator.generate_contacts();
  659. }
  660. template <bool castA, bool castB, bool withMargin>
  661. static void _collision_circle_convex_polygon(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  662. const CircleShape2DSW *circle_A = static_cast<const CircleShape2DSW *>(p_a);
  663. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  664. 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);
  665. if (!separator.test_previous_axis())
  666. return;
  667. if (!separator.test_cast())
  668. return;
  669. //poly faces and poly points vs circle
  670. for (int i = 0; i < convex_B->get_point_count(); i++) {
  671. if (TEST_POINT(p_transform_a.get_origin(), p_transform_b.xform(convex_B->get_point(i))))
  672. return;
  673. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  674. return;
  675. }
  676. separator.generate_contacts();
  677. }
  678. /////////
  679. template <bool castA, bool castB, bool withMargin>
  680. static void _collision_rectangle_rectangle(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  681. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  682. const RectangleShape2DSW *rectangle_B = static_cast<const RectangleShape2DSW *>(p_b);
  683. 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);
  684. if (!separator.test_previous_axis())
  685. return;
  686. if (!separator.test_cast())
  687. return;
  688. //box faces A
  689. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  690. return;
  691. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  692. return;
  693. //box faces B
  694. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  695. return;
  696. if (!separator.test_axis(p_transform_b.elements[1].normalized()))
  697. return;
  698. if (withMargin) {
  699. Matrix32 invA = p_transform_a.affine_inverse();
  700. Matrix32 invB = p_transform_b.affine_inverse();
  701. if (!separator.test_axis(rectangle_A->get_box_axis(p_transform_a, invA, rectangle_B, p_transform_b, invB)))
  702. return;
  703. if (castA || castB) {
  704. Matrix32 aofs = p_transform_a;
  705. aofs.elements[2] += p_motion_a;
  706. Matrix32 bofs = p_transform_b;
  707. bofs.elements[2] += p_motion_b;
  708. Matrix32 aofsinv = aofs.affine_inverse();
  709. Matrix32 bofsinv = bofs.affine_inverse();
  710. if (castA) {
  711. if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, p_transform_b, invB)))
  712. return;
  713. }
  714. if (castB) {
  715. if (!separator.test_axis(rectangle_A->get_box_axis(p_transform_a, invA, rectangle_B, bofs, bofsinv)))
  716. return;
  717. }
  718. if (castA && castB) {
  719. if (!separator.test_axis(rectangle_A->get_box_axis(aofs, aofsinv, rectangle_B, bofs, bofsinv)))
  720. return;
  721. }
  722. }
  723. }
  724. separator.generate_contacts();
  725. }
  726. template <bool castA, bool castB, bool withMargin>
  727. static void _collision_rectangle_capsule(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  728. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  729. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  730. 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);
  731. if (!separator.test_previous_axis())
  732. return;
  733. if (!separator.test_cast())
  734. return;
  735. //box faces
  736. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  737. return;
  738. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  739. return;
  740. //capsule axis
  741. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  742. return;
  743. //box endpoints to capsule circles
  744. Matrix32 boxinv = p_transform_a.affine_inverse();
  745. for (int i = 0; i < 2; i++) {
  746. {
  747. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  748. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  749. return;
  750. }
  751. if (castA) {
  752. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  753. capsule_endpoint -= p_motion_a;
  754. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  755. return;
  756. }
  757. if (castB) {
  758. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  759. capsule_endpoint += p_motion_b;
  760. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  761. return;
  762. }
  763. if (castA && castB) {
  764. Vector2 capsule_endpoint = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (i == 0 ? 0.5 : -0.5);
  765. capsule_endpoint -= p_motion_a;
  766. capsule_endpoint += p_motion_b;
  767. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, capsule_endpoint)))
  768. return;
  769. }
  770. }
  771. separator.generate_contacts();
  772. }
  773. template <bool castA, bool castB, bool withMargin>
  774. static void _collision_rectangle_convex_polygon(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  775. const RectangleShape2DSW *rectangle_A = static_cast<const RectangleShape2DSW *>(p_a);
  776. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  777. 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);
  778. if (!separator.test_previous_axis())
  779. return;
  780. if (!separator.test_cast())
  781. return;
  782. //box faces
  783. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  784. return;
  785. if (!separator.test_axis(p_transform_a.elements[1].normalized()))
  786. return;
  787. //convex faces
  788. Matrix32 boxinv;
  789. if (withMargin) {
  790. boxinv = p_transform_a.affine_inverse();
  791. }
  792. for (int i = 0; i < convex_B->get_point_count(); i++) {
  793. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  794. return;
  795. if (withMargin) {
  796. //all points vs all points need to be tested if margin exist
  797. if (!separator.test_axis(rectangle_A->get_circle_axis(p_transform_a, boxinv, p_transform_b.xform(convex_B->get_point(i)))))
  798. return;
  799. if (castA) {
  800. 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)))
  801. return;
  802. }
  803. if (castB) {
  804. 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)))
  805. return;
  806. }
  807. if (castA && castB) {
  808. 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)))
  809. return;
  810. }
  811. }
  812. }
  813. separator.generate_contacts();
  814. }
  815. /////////
  816. template <bool castA, bool castB, bool withMargin>
  817. static void _collision_capsule_capsule(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  818. const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
  819. const CapsuleShape2DSW *capsule_B = static_cast<const CapsuleShape2DSW *>(p_b);
  820. 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);
  821. if (!separator.test_previous_axis())
  822. return;
  823. if (!separator.test_cast())
  824. return;
  825. //capsule axis
  826. if (!separator.test_axis(p_transform_b.elements[0].normalized()))
  827. return;
  828. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  829. return;
  830. //capsule endpoints
  831. for (int i = 0; i < 2; i++) {
  832. Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (i == 0 ? 0.5 : -0.5);
  833. for (int j = 0; j < 2; j++) {
  834. Vector2 capsule_endpoint_B = p_transform_b.get_origin() + p_transform_b.elements[1] * capsule_B->get_height() * (j == 0 ? 0.5 : -0.5);
  835. if (TEST_POINT(capsule_endpoint_A, capsule_endpoint_B))
  836. return;
  837. }
  838. }
  839. separator.generate_contacts();
  840. }
  841. template <bool castA, bool castB, bool withMargin>
  842. static void _collision_capsule_convex_polygon(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  843. const CapsuleShape2DSW *capsule_A = static_cast<const CapsuleShape2DSW *>(p_a);
  844. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  845. 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);
  846. if (!separator.test_previous_axis())
  847. return;
  848. if (!separator.test_cast())
  849. return;
  850. //capsule axis
  851. if (!separator.test_axis(p_transform_a.elements[0].normalized()))
  852. return;
  853. //poly vs capsule
  854. for (int i = 0; i < convex_B->get_point_count(); i++) {
  855. Vector2 cpoint = p_transform_b.xform(convex_B->get_point(i));
  856. for (int j = 0; j < 2; j++) {
  857. Vector2 capsule_endpoint_A = p_transform_a.get_origin() + p_transform_a.elements[1] * capsule_A->get_height() * (j == 0 ? 0.5 : -0.5);
  858. if (TEST_POINT(capsule_endpoint_A, cpoint))
  859. return;
  860. }
  861. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  862. return;
  863. }
  864. separator.generate_contacts();
  865. }
  866. /////////
  867. template <bool castA, bool castB, bool withMargin>
  868. static void _collision_convex_polygon_convex_polygon(const Shape2DSW *p_a, const Matrix32 &p_transform_a, const Shape2DSW *p_b, const Matrix32 &p_transform_b, _CollectorCallback2D *p_collector, const Vector2 &p_motion_a, const Vector2 &p_motion_b, float p_margin_A, float p_margin_B) {
  869. const ConvexPolygonShape2DSW *convex_A = static_cast<const ConvexPolygonShape2DSW *>(p_a);
  870. const ConvexPolygonShape2DSW *convex_B = static_cast<const ConvexPolygonShape2DSW *>(p_b);
  871. 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);
  872. if (!separator.test_previous_axis())
  873. return;
  874. if (!separator.test_cast())
  875. return;
  876. for (int i = 0; i < convex_A->get_point_count(); i++) {
  877. if (!separator.test_axis(convex_A->get_xformed_segment_normal(p_transform_a, i)))
  878. return;
  879. }
  880. for (int i = 0; i < convex_B->get_point_count(); i++) {
  881. if (!separator.test_axis(convex_B->get_xformed_segment_normal(p_transform_b, i)))
  882. return;
  883. }
  884. if (withMargin) {
  885. for (int i = 0; i < convex_A->get_point_count(); i++) {
  886. for (int j = 0; j < convex_B->get_point_count(); j++) {
  887. if (TEST_POINT(p_transform_a.xform(convex_A->get_point(i)), p_transform_b.xform(convex_B->get_point(j))))
  888. return;
  889. }
  890. }
  891. }
  892. separator.generate_contacts();
  893. }
  894. ////////
  895. bool sat_2d_calculate_penetration(const Shape2DSW *p_shape_A, const Matrix32 &p_transform_A, const Vector2 &p_motion_A, const Shape2DSW *p_shape_B, const Matrix32 &p_transform_B, const Vector2 &p_motion_B, CollisionSolver2DSW::CallbackResult p_result_callback, void *p_userdata, bool p_swap, Vector2 *sep_axis, float p_margin_A, float p_margin_B) {
  896. Physics2DServer::ShapeType type_A = p_shape_A->get_type();
  897. ERR_FAIL_COND_V(type_A == Physics2DServer::SHAPE_LINE, false);
  898. //ERR_FAIL_COND_V(type_A==Physics2DServer::SHAPE_RAY,false);
  899. ERR_FAIL_COND_V(p_shape_A->is_concave(), false);
  900. Physics2DServer::ShapeType type_B = p_shape_B->get_type();
  901. ERR_FAIL_COND_V(type_B == Physics2DServer::SHAPE_LINE, false);
  902. //ERR_FAIL_COND_V(type_B==Physics2DServer::SHAPE_RAY,false);
  903. ERR_FAIL_COND_V(p_shape_B->is_concave(), false);
  904. static const CollisionFunc collision_table[5][5] = {
  905. { _collision_segment_segment<false, false, false>,
  906. _collision_segment_circle<false, false, false>,
  907. _collision_segment_rectangle<false, false, false>,
  908. _collision_segment_capsule<false, false, false>,
  909. _collision_segment_convex_polygon<false, false, false> },
  910. { 0,
  911. _collision_circle_circle<false, false, false>,
  912. _collision_circle_rectangle<false, false, false>,
  913. _collision_circle_capsule<false, false, false>,
  914. _collision_circle_convex_polygon<false, false, false> },
  915. { 0,
  916. 0,
  917. _collision_rectangle_rectangle<false, false, false>,
  918. _collision_rectangle_capsule<false, false, false>,
  919. _collision_rectangle_convex_polygon<false, false, false> },
  920. { 0,
  921. 0,
  922. 0,
  923. _collision_capsule_capsule<false, false, false>,
  924. _collision_capsule_convex_polygon<false, false, false> },
  925. { 0,
  926. 0,
  927. 0,
  928. 0,
  929. _collision_convex_polygon_convex_polygon<false, false, false> }
  930. };
  931. static const CollisionFunc collision_table_castA[5][5] = {
  932. { _collision_segment_segment<true, false, false>,
  933. _collision_segment_circle<true, false, false>,
  934. _collision_segment_rectangle<true, false, false>,
  935. _collision_segment_capsule<true, false, false>,
  936. _collision_segment_convex_polygon<true, false, false> },
  937. { 0,
  938. _collision_circle_circle<true, false, false>,
  939. _collision_circle_rectangle<true, false, false>,
  940. _collision_circle_capsule<true, false, false>,
  941. _collision_circle_convex_polygon<true, false, false> },
  942. { 0,
  943. 0,
  944. _collision_rectangle_rectangle<true, false, false>,
  945. _collision_rectangle_capsule<true, false, false>,
  946. _collision_rectangle_convex_polygon<true, false, false> },
  947. { 0,
  948. 0,
  949. 0,
  950. _collision_capsule_capsule<true, false, false>,
  951. _collision_capsule_convex_polygon<true, false, false> },
  952. { 0,
  953. 0,
  954. 0,
  955. 0,
  956. _collision_convex_polygon_convex_polygon<true, false, false> }
  957. };
  958. static const CollisionFunc collision_table_castB[5][5] = {
  959. { _collision_segment_segment<false, true, false>,
  960. _collision_segment_circle<false, true, false>,
  961. _collision_segment_rectangle<false, true, false>,
  962. _collision_segment_capsule<false, true, false>,
  963. _collision_segment_convex_polygon<false, true, false> },
  964. { 0,
  965. _collision_circle_circle<false, true, false>,
  966. _collision_circle_rectangle<false, true, false>,
  967. _collision_circle_capsule<false, true, false>,
  968. _collision_circle_convex_polygon<false, true, false> },
  969. { 0,
  970. 0,
  971. _collision_rectangle_rectangle<false, true, false>,
  972. _collision_rectangle_capsule<false, true, false>,
  973. _collision_rectangle_convex_polygon<false, true, false> },
  974. { 0,
  975. 0,
  976. 0,
  977. _collision_capsule_capsule<false, true, false>,
  978. _collision_capsule_convex_polygon<false, true, false> },
  979. { 0,
  980. 0,
  981. 0,
  982. 0,
  983. _collision_convex_polygon_convex_polygon<false, true, false> }
  984. };
  985. static const CollisionFunc collision_table_castA_castB[5][5] = {
  986. { _collision_segment_segment<true, true, false>,
  987. _collision_segment_circle<true, true, false>,
  988. _collision_segment_rectangle<true, true, false>,
  989. _collision_segment_capsule<true, true, false>,
  990. _collision_segment_convex_polygon<true, true, false> },
  991. { 0,
  992. _collision_circle_circle<true, true, false>,
  993. _collision_circle_rectangle<true, true, false>,
  994. _collision_circle_capsule<true, true, false>,
  995. _collision_circle_convex_polygon<true, true, false> },
  996. { 0,
  997. 0,
  998. _collision_rectangle_rectangle<true, true, false>,
  999. _collision_rectangle_capsule<true, true, false>,
  1000. _collision_rectangle_convex_polygon<true, true, false> },
  1001. { 0,
  1002. 0,
  1003. 0,
  1004. _collision_capsule_capsule<true, true, false>,
  1005. _collision_capsule_convex_polygon<true, true, false> },
  1006. { 0,
  1007. 0,
  1008. 0,
  1009. 0,
  1010. _collision_convex_polygon_convex_polygon<true, true, false> }
  1011. };
  1012. static const CollisionFunc collision_table_margin[5][5] = {
  1013. { _collision_segment_segment<false, false, true>,
  1014. _collision_segment_circle<false, false, true>,
  1015. _collision_segment_rectangle<false, false, true>,
  1016. _collision_segment_capsule<false, false, true>,
  1017. _collision_segment_convex_polygon<false, false, true> },
  1018. { 0,
  1019. _collision_circle_circle<false, false, true>,
  1020. _collision_circle_rectangle<false, false, true>,
  1021. _collision_circle_capsule<false, false, true>,
  1022. _collision_circle_convex_polygon<false, false, true> },
  1023. { 0,
  1024. 0,
  1025. _collision_rectangle_rectangle<false, false, true>,
  1026. _collision_rectangle_capsule<false, false, true>,
  1027. _collision_rectangle_convex_polygon<false, false, true> },
  1028. { 0,
  1029. 0,
  1030. 0,
  1031. _collision_capsule_capsule<false, false, true>,
  1032. _collision_capsule_convex_polygon<false, false, true> },
  1033. { 0,
  1034. 0,
  1035. 0,
  1036. 0,
  1037. _collision_convex_polygon_convex_polygon<false, false, true> }
  1038. };
  1039. static const CollisionFunc collision_table_castA_margin[5][5] = {
  1040. { _collision_segment_segment<true, false, true>,
  1041. _collision_segment_circle<true, false, true>,
  1042. _collision_segment_rectangle<true, false, true>,
  1043. _collision_segment_capsule<true, false, true>,
  1044. _collision_segment_convex_polygon<true, false, true> },
  1045. { 0,
  1046. _collision_circle_circle<true, false, true>,
  1047. _collision_circle_rectangle<true, false, true>,
  1048. _collision_circle_capsule<true, false, true>,
  1049. _collision_circle_convex_polygon<true, false, true> },
  1050. { 0,
  1051. 0,
  1052. _collision_rectangle_rectangle<true, false, true>,
  1053. _collision_rectangle_capsule<true, false, true>,
  1054. _collision_rectangle_convex_polygon<true, false, true> },
  1055. { 0,
  1056. 0,
  1057. 0,
  1058. _collision_capsule_capsule<true, false, true>,
  1059. _collision_capsule_convex_polygon<true, false, true> },
  1060. { 0,
  1061. 0,
  1062. 0,
  1063. 0,
  1064. _collision_convex_polygon_convex_polygon<true, false, true> }
  1065. };
  1066. static const CollisionFunc collision_table_castB_margin[5][5] = {
  1067. { _collision_segment_segment<false, true, true>,
  1068. _collision_segment_circle<false, true, true>,
  1069. _collision_segment_rectangle<false, true, true>,
  1070. _collision_segment_capsule<false, true, true>,
  1071. _collision_segment_convex_polygon<false, true, true> },
  1072. { 0,
  1073. _collision_circle_circle<false, true, true>,
  1074. _collision_circle_rectangle<false, true, true>,
  1075. _collision_circle_capsule<false, true, true>,
  1076. _collision_circle_convex_polygon<false, true, true> },
  1077. { 0,
  1078. 0,
  1079. _collision_rectangle_rectangle<false, true, true>,
  1080. _collision_rectangle_capsule<false, true, true>,
  1081. _collision_rectangle_convex_polygon<false, true, true> },
  1082. { 0,
  1083. 0,
  1084. 0,
  1085. _collision_capsule_capsule<false, true, true>,
  1086. _collision_capsule_convex_polygon<false, true, true> },
  1087. { 0,
  1088. 0,
  1089. 0,
  1090. 0,
  1091. _collision_convex_polygon_convex_polygon<false, true, true> }
  1092. };
  1093. static const CollisionFunc collision_table_castA_castB_margin[5][5] = {
  1094. { _collision_segment_segment<true, true, true>,
  1095. _collision_segment_circle<true, true, true>,
  1096. _collision_segment_rectangle<true, true, true>,
  1097. _collision_segment_capsule<true, true, true>,
  1098. _collision_segment_convex_polygon<true, true, true> },
  1099. { 0,
  1100. _collision_circle_circle<true, true, true>,
  1101. _collision_circle_rectangle<true, true, true>,
  1102. _collision_circle_capsule<true, true, true>,
  1103. _collision_circle_convex_polygon<true, true, true> },
  1104. { 0,
  1105. 0,
  1106. _collision_rectangle_rectangle<true, true, true>,
  1107. _collision_rectangle_capsule<true, true, true>,
  1108. _collision_rectangle_convex_polygon<true, true, true> },
  1109. { 0,
  1110. 0,
  1111. 0,
  1112. _collision_capsule_capsule<true, true, true>,
  1113. _collision_capsule_convex_polygon<true, true, true> },
  1114. { 0,
  1115. 0,
  1116. 0,
  1117. 0,
  1118. _collision_convex_polygon_convex_polygon<true, true, true> }
  1119. };
  1120. _CollectorCallback2D callback;
  1121. callback.callback = p_result_callback;
  1122. callback.swap = p_swap;
  1123. callback.userdata = p_userdata;
  1124. callback.collided = false;
  1125. callback.sep_axis = sep_axis;
  1126. const Shape2DSW *A = p_shape_A;
  1127. const Shape2DSW *B = p_shape_B;
  1128. const Matrix32 *transform_A = &p_transform_A;
  1129. const Matrix32 *transform_B = &p_transform_B;
  1130. const Vector2 *motion_A = &p_motion_A;
  1131. const Vector2 *motion_B = &p_motion_B;
  1132. real_t margin_A = p_margin_A, margin_B = p_margin_B;
  1133. if (type_A > type_B) {
  1134. SWAP(A, B);
  1135. SWAP(transform_A, transform_B);
  1136. SWAP(type_A, type_B);
  1137. SWAP(motion_A, motion_B);
  1138. SWAP(margin_A, margin_B);
  1139. callback.swap = !callback.swap;
  1140. }
  1141. CollisionFunc collision_func;
  1142. if (p_margin_A || p_margin_B) {
  1143. if (*motion_A == Vector2() && *motion_B == Vector2()) {
  1144. collision_func = collision_table_margin[type_A - 2][type_B - 2];
  1145. } else if (*motion_A != Vector2() && *motion_B == Vector2()) {
  1146. collision_func = collision_table_castA_margin[type_A - 2][type_B - 2];
  1147. } else if (*motion_A == Vector2() && *motion_B != Vector2()) {
  1148. collision_func = collision_table_castB_margin[type_A - 2][type_B - 2];
  1149. } else {
  1150. collision_func = collision_table_castA_castB_margin[type_A - 2][type_B - 2];
  1151. }
  1152. } else {
  1153. if (*motion_A == Vector2() && *motion_B == Vector2()) {
  1154. collision_func = collision_table[type_A - 2][type_B - 2];
  1155. } else if (*motion_A != Vector2() && *motion_B == Vector2()) {
  1156. collision_func = collision_table_castA[type_A - 2][type_B - 2];
  1157. } else if (*motion_A == Vector2() && *motion_B != Vector2()) {
  1158. collision_func = collision_table_castB[type_A - 2][type_B - 2];
  1159. } else {
  1160. collision_func = collision_table_castA_castB[type_A - 2][type_B - 2];
  1161. }
  1162. }
  1163. ERR_FAIL_COND_V(!collision_func, false);
  1164. collision_func(A, *transform_A, B, *transform_B, &callback, *motion_A, *motion_B, margin_A, margin_B);
  1165. return callback.collided;
  1166. }