gs_physics.h 68 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735
  1. /*==============================================================================================================
  2. * Copyright (c) 2020 John Jackson
  3. * GSPhysics: Simple 3D/2D physics engine
  4. * File: gs_physics.h
  5. * Github: https://github.com/MrFrenik/gunslinger
  6. * All Rights Reserved
  7. * MIT License
  8. * May all those that this source may reach be blessed by the LORD and find peace and joy in life.
  9. * Everyone who drinks of this water will be thirsty again; but whoever drinks of the water
  10. * that I will give him shall never thirst; John 4:13-14
  11. * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
  12. * documentation files (the "Software"), to deal in the Software without restriction, including without limitation
  13. * the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
  14. * and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
  15. * The above copyright, blessing, biblical verse, notice and this permission notice shall be included in all
  16. * copies or substantial portions of the Software.
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED
  18. * TO THE WARRANTIES OF MECHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
  20. * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  21. * IN THE SOFTWARE.
  22. =================================================================================================================*/
  23. #ifndef GS_PHYSICS_H
  24. #define GS_PHYSICS_H
  25. /*
  26. USAGE: (IMPORTANT)
  27. =================================================================================================================
  28. Before including, define the gunslinger physics implementation like this:
  29. #define GS_PHYSICS_IMPL
  30. in EXACTLY ONE C or C++ file that includes this header, BEFORE the
  31. include, like this:
  32. #define GS_PHYSICS_IMPL
  33. #include "gs_physics.h"
  34. All other files should just #include "gs_physics.h" without the #define.
  35. MUST include "gs.h" and declare GS_IMPL BEFORE this file, since this file relies on that:
  36. #define GS_IMPL
  37. #include "gs.h"
  38. #define GS_PHYSICS_IMPL
  39. #include "gs_physics.h"
  40. Special Thanks for reference:
  41. - https://github.com/r-lyeh (for collision algorithms)
  42. - https://gist.github.com/vurtun/95f088e4889da2474ad1ce82d7911fee (for GJK impl)
  43. - Randy Gaul (for physics system inspiration)
  44. - https://github.com/Nightmask3/Physics-Framework
  45. - https://github.com/IainWinter/IwEngine/tree/master/IwEngine/src/physics
  46. +
  47. ================================================================================================================
  48. */
  49. /*==== Interface ====*/
  50. /** @defgroup gs_physics_util Physics Util
  51. * Gunslinger Physics Util
  52. * @{
  53. */
  54. /*==== Collision Shapes ====*/
  55. // 3D shapes
  56. typedef struct gs_line_t
  57. {
  58. gs_vec3 a, b;
  59. } gs_line_t;
  60. typedef struct gs_aabb_t
  61. {
  62. gs_vec3 min, max;
  63. } gs_aabb_t;
  64. typedef struct gs_sphere_t
  65. {
  66. gs_vec3 c; float r;
  67. } gs_sphere_t;
  68. typedef struct gs_plane_t
  69. {
  70. union{
  71. gs_vec3 p;
  72. struct{float a, b, c;};
  73. };
  74. float d;
  75. } gs_plane_t;
  76. typedef struct gs_capsule_t
  77. {
  78. gs_vec3 base;
  79. float r, height;
  80. } gs_capsule_t;
  81. typedef struct gs_ray_s
  82. {
  83. gs_vec3 p, d;
  84. float len;
  85. } gs_ray_t;
  86. typedef struct gs_poly_t
  87. {
  88. gs_vec3* verts; int32_t cnt;
  89. } gs_poly_t;
  90. typedef union gs_frustum_t
  91. {
  92. struct {
  93. gs_vec4 l, r, t, b, n, f;
  94. };
  95. gs_vec4 pl[6];
  96. float v[24];
  97. } gs_frustum_t;
  98. typedef struct gs_cylinder_t
  99. {
  100. float r;
  101. gs_vec3 base;
  102. float height;
  103. } gs_cylinder_t;
  104. typedef struct gs_cone_t
  105. {
  106. float r;
  107. gs_vec3 base;
  108. float height;
  109. } gs_cone_t;
  110. // 2D shapes
  111. typedef struct gs_circle_t {float r; gs_vec2 c; } gs_circle_t;
  112. // typedef struct gs_rect_t {gs_vec2 min; gs_vec2 max; } gs_rect_t;
  113. // typedef struct gs_triangle_t {gs_vec2 a,b,c; } gs_triangle_t;
  114. // typedef struct gs_pill_t {gs_vec2 base; float r, height; } gs_pill_t;
  115. /*
  116. typedef struct _gs_collision_obj_handle_t
  117. {
  118. void* obj;
  119. gs_support_func_t support;
  120. gs_vqs* xform;
  121. } _gs_collision_obj_handle_t;
  122. // Wrap this, then expose collision callback to user through gs means
  123. // Internal support function for all ccd callbacks (will pass in user function through this cb),
  124. // this way I can keep everything consistent, only expose gs related APIs, wrap any 3rd party libs,
  125. // and possibly change internals in the future to custom implementations without breaking anything.
  126. void _gs_ccd_support_func(const void* _obj, const ccd_vec3_t* _dir, ccd_vec3_t* _out)
  127. {
  128. const _gs_collision_obj_handle_t* obj = (const _gs_collision_obj_handle_t)_obj;
  129. if (obj->support)
  130. {
  131. // Call user support function
  132. gs_vec3 dir = _gs_ccdv32gsv3(_dir);
  133. gs_vec3 out = gs_default_val();
  134. obj->support(obj->obj, obj->xform, &dir, &out);
  135. // Copy over out result for ccd
  136. _gs_gsv32ccdv3(&out, _out);
  137. }
  138. }
  139. */
  140. // Need 2d collision shapes and responses with GJK+EPA
  141. typedef struct gs_hit_t {
  142. int32_t hit;
  143. union {
  144. // General case
  145. float depth;
  146. // Rays: Penetration (t0) and Extraction (t1) pts. along ray line
  147. struct {float t0, t1;};
  148. // GJK only
  149. struct {int32_t hits, iterations; gs_vec3 p0, p1; float distance2;};
  150. };
  151. union {gs_vec3 p; gs_vec3 contact_point;};
  152. union {gs_vec3 n; gs_vec3 normal;};
  153. } gs_hit_t;
  154. // Constructors with args
  155. #define gs_line(...) gs_ctor(gs_line_t, __VA_ARGS__)
  156. #define gs_sphere(...) gs_ctor(gs_sphere_t, __VA_ARGS__)
  157. #define gs_aabb(...) gs_ctor(gs_aabb_t, __VA_ARGS__)
  158. #define gs_plane(...) gs_ctor(gs_plane_t, __VA_ARGS__)
  159. #define gs_capsule(...) gs_ctor(gs_capsule_t, __VA_ARGS__)
  160. #define gs_cone(...) gs_ctor(gs_cone_t, __VA_ARGS__)
  161. #define gs_ray(...) gs_ctor(gs_ray_t, __VA_ARGS__)
  162. #define gs_poly(...) gs_ctor(gs_poly_t, __VA_ARGS__)
  163. #define gs_frustum(...). gs_ctor(gs_frustum_t, __VA_ARGS__)
  164. #define gs_cylinder(...) gs_ctor(gs_cylinder_t, __VA_ARGS__)
  165. #define gs_hit(...) gs_ctor(gs_hit_t, __VA_ARGS__)
  166. // Contact info
  167. typedef struct gs_contact_info_t {
  168. int32_t hit;
  169. gs_vec3 normal;
  170. float depth;
  171. gs_vec3 point;
  172. } gs_contact_info_t;
  173. /* Line/Segment */
  174. GS_API_DECL gs_line_t gs_line_closest_line(const gs_line_t* l, gs_vec3 p);
  175. GS_API_DECL gs_vec3 gs_line_closest_point(const gs_line_t* l, gs_vec3 p);
  176. GS_API_DECL gs_vec3 gs_line_direction(const gs_line_t* l);
  177. /* Ray */
  178. /* Plane */
  179. GS_API_DECL gs_plane_t gs_plane_from_pt_normal(gs_vec3 pt, gs_vec3 n);
  180. GS_API_DECL gs_plane_t gs_plane_from_pts(gs_vec3 a, gs_vec3 b, gs_vec3 c);
  181. GS_API_DECL gs_vec3 gs_plane_normal(const gs_plane_t* p);
  182. GS_API_DECL gs_vec3 gs_plane_closest_point(const gs_plane_t* p, gs_vec3 pt);
  183. GS_API_DECL float gs_plane_signed_distance(const gs_plane_t* p, gs_vec3 pt);
  184. GS_API_DECL float gs_plane_unsigned_distance(const gs_plane_t* p, gs_vec3 pt);
  185. GS_API_DECL gs_plane_t gs_plane_normalized(const gs_plane_t* p);
  186. /* Sphere */
  187. GS_API_DECL int32_t gs_sphere_vs_sphere(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  188. GS_API_DECL int32_t gs_sphere_vs_aabb(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  189. GS_API_DECL int32_t gs_sphere_vs_poly(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  190. GS_API_DECL int32_t gs_sphere_vs_cylinder(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  191. GS_API_DECL int32_t gs_sphere_vs_cone(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  192. GS_API_DECL int32_t gs_sphere_vs_capsule(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  193. GS_API_DECL int32_t gs_sphere_vs_ray(const gs_sphere_t* a, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  194. /* Box */
  195. GS_API_DECL int32_t gs_aabb_vs_aabb(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  196. GS_API_DECL int32_t gs_aabb_vs_sphere(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  197. GS_API_DECL int32_t gs_aabb_vs_poly(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  198. GS_API_DECL int32_t gs_aabb_vs_cylinder(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  199. GS_API_DECL int32_t gs_aabb_vs_cone(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  200. GS_API_DECL int32_t gs_aabb_vs_capsule(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  201. GS_API_DECL int32_t gs_aabb_vs_ray(const gs_aabb_t* a, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  202. /* Capsule */
  203. GS_API_DECL int32_t gs_capsule_vs_aabb(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  204. GS_API_DECL int32_t gs_capsule_vs_sphere(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  205. GS_API_DECL int32_t gs_capsule_vs_poly(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  206. GS_API_DECL int32_t gs_capsule_vs_cylinder(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  207. GS_API_DECL int32_t gs_capsule_vs_cone(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  208. GS_API_DECL int32_t gs_capsule_vs_capsule(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  209. GS_API_DECL int32_t gs_capsule_vs_ray(const gs_capsule_t* capsule, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  210. /* Poly */
  211. GS_API_DECL int32_t gs_poly_vs_poly(const gs_poly_t* a, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  212. GS_API_DECL int32_t gs_poly_vs_sphere(const gs_poly_t* a, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  213. GS_API_DECL int32_t gs_poly_vs_aabb(const gs_poly_t* a, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  214. GS_API_DECL int32_t gs_poly_vs_cylinder(const gs_poly_t* a, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  215. GS_API_DECL int32_t gs_poly_vs_cone(const gs_poly_t* a, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  216. GS_API_DECL int32_t gs_poly_vs_capsule(const gs_poly_t* a, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  217. GS_API_DECL int32_t gs_poly_vs_ray(const gs_poly_t* a, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  218. /* Frustum */
  219. /* Cylinder */
  220. GS_API_DECL int32_t gs_cylinder_vs_cylinder(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  221. GS_API_DECL int32_t gs_cylinder_vs_sphere(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  222. GS_API_DECL int32_t gs_cylinder_vs_aabb(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  223. GS_API_DECL int32_t gs_cylinder_vs_poly(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  224. GS_API_DECL int32_t gs_cylinder_vs_cone(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  225. GS_API_DECL int32_t gs_cylinder_vs_capsule(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  226. GS_API_DECL int32_t gs_cylinder_vs_ray(const gs_cylinder_t* a, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  227. /* Cone */
  228. GS_API_DECL int32_t gs_cone_vs_cone(const gs_cone_t* a, const gs_vqs* xform_a, const gs_cone_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  229. GS_API_DECL int32_t gs_cone_vs_sphere(const gs_cone_t* a, const gs_vqs* xform_a, const gs_sphere_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  230. GS_API_DECL int32_t gs_cone_vs_aabb(const gs_cone_t* a, const gs_vqs* xform_a, const gs_aabb_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  231. GS_API_DECL int32_t gs_cone_vs_poly(const gs_cone_t* a, const gs_vqs* xform_a, const gs_poly_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  232. GS_API_DECL int32_t gs_cone_vs_cylinder(const gs_cone_t* a, const gs_vqs* xform_a, const gs_cylinder_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  233. GS_API_DECL int32_t gs_cone_vs_capsule(const gs_cone_t* a, const gs_vqs* xform_a, const gs_capsule_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  234. GS_API_DECL int32_t gs_cone_vs_ray(const gs_cone_t* a, const gs_vqs* xform_a, const gs_ray_t* b, const gs_vqs* xform_b, gs_contact_info_t* res);
  235. // 2D Shapes (eventually)
  236. /* Hit */
  237. /*==== Support Functions ====*/
  238. // Support function typedef for GJK collision detection
  239. typedef void (* gs_support_func_t)(const void* collider, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  240. GS_API_DECL void gs_support_poly(const void* p, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  241. GS_API_DECL void gs_support_sphere(const void* s, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  242. GS_API_DECL void gs_support_aabb(const void* a, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  243. GS_API_DECL void gs_support_cylinder(const void* c, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  244. GS_API_DECL void gs_support_cone(const void* c, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  245. GS_API_DECL void gs_support_capsule(const void* c, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  246. GS_API_DECL void gs_support_ray(const void* r, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out);
  247. /*==== GJK ====*/
  248. #define GS_GJK_FLT_MAX FLT_MAX // 3.40282347E+38F
  249. #define GS_GJK_EPSILON FLT_EPSILON // 1.19209290E-07F
  250. #define GS_GJK_MAX_ITERATIONS 64
  251. #define GS_EPA_TOLERANCE 0.0001
  252. #define GS_EPA_MAX_NUM_FACES 64
  253. #define GS_EPA_MAX_NUM_LOOSE_EDGES 32
  254. #define GS_EPA_MAX_NUM_ITERATIONS 64
  255. typedef enum gs_gjk_dimension {
  256. GS_GJK_DIMENSION_2D,
  257. GS_GJK_DIMENSION_3D
  258. } gs_gjk_dimension;
  259. typedef struct gs_gjk_support_point_t {
  260. gs_vec3 support_a;
  261. gs_vec3 support_b;
  262. gs_vec3 minkowski_hull_vert;
  263. } gs_gjk_support_point_t;
  264. typedef struct gs_gjk_simplex_t {
  265. union {
  266. gs_gjk_support_point_t points[4];
  267. struct {
  268. gs_gjk_support_point_t a;
  269. gs_gjk_support_point_t b;
  270. gs_gjk_support_point_t c;
  271. gs_gjk_support_point_t d;
  272. };
  273. };
  274. uint32_t ct;
  275. } gs_gjk_simplex_t;
  276. typedef struct gs_gjk_polytope_face_t {
  277. gs_gjk_support_point_t points[3];
  278. gs_vec3 normal;
  279. } gs_gjk_polytope_face_t;
  280. typedef struct gs_gjk_epa_edge_t {
  281. gs_vec3 normal;
  282. uint32_t index;
  283. float distance;
  284. gs_gjk_support_point_t a, b;
  285. } gs_gjk_epa_edge_t;
  286. // GS_API_DECL int32_t gs_gjk(const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1, gs_gjk_dimension dimension, gs_contact_info_t* res);
  287. // GS_API_DECL gs_contact_info_t gs_gjk_epa(const gs_gjk_simplex_t* simplex, const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1);
  288. // GS_API_DECL gs_contact_info_t gs_gjk_epa_2d(const gs_gjk_simplex_t* simplex, const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1);
  289. // GS_API_DECL gs_gjk_collider_info_t gs_gjk_collider_info(void* c, gs_support_func_t f, gs_phys_xform_t* t);
  290. //
  291. GS_API_PRIVATE int32_t _gs_ccd_gjk_internal(const void* c0, const gs_vqs* xform_a, gs_support_func_t f0, const void* c1, const gs_vqs* xform_b, gs_support_func_t f1, gs_contact_info_t* res);
  292. /*==== CCD ====*/
  293. #ifndef GS_PHYSICS_NO_CCD
  294. #include "../external/ccd/src/ccd/ccd_vec3.h"
  295. // Internal collision object conversion handle
  296. typedef struct _gs_collision_obj_handle_t
  297. {
  298. const void* obj;
  299. gs_support_func_t support;
  300. const gs_vqs* xform;
  301. } _gs_collision_obj_handle_t;
  302. // Internal support function for all ccd callbacks (will pass in user function through this cb),
  303. // this way I can keep everything consistent, only expose gs related APIs, wrap any 3rd party libs,
  304. // and possibly change internals in the future to custom implementations without breaking anything.
  305. GS_API_DECL void _gs_ccd_support_func(const void* _obj, const ccd_vec3_t* _dir, ccd_vec3_t* _out);
  306. GS_API_DECL int32_t _gs_ccd_gjk(const _gs_collision_obj_handle_t* c0, const _gs_collision_obj_handle_t* c1, gs_contact_info_t* res);
  307. #endif // GS_PHYSICS_NO_CCD
  308. /*==== Physics System ====*/
  309. #define EMPTY_VAR(...) int32_t __empty
  310. /* Rigid Body */
  311. // Just want a single collision shape...not sure exactly how to handle this.
  312. // Probably keep the data for the collision shape within the scene itself (or physics system)? Then give handles to users for the data.
  313. typedef enum gs_rigid_body_type {
  314. GS_RIGID_BODY_STATIC,
  315. GS_RIGID_BODY_DYNAMIC,
  316. GS_RIGID_BODY_KINEMATIC
  317. } gs_rigid_body_type;
  318. typedef enum gs_rigid_body_state_flags {
  319. GS_RIGID_BODY_STATE_AWAKE = 0x001,
  320. GS_RIGID_BODY_STATE_ACTIVE = 0x002,
  321. GS_RIGID_BODY_STATE_ALLOW_SLEEP = 0x004,
  322. GS_RIGID_BODY_STATE_ISLAND = 0x010,
  323. GS_RIGID_BODY_STATE_STATIC = 0x020,
  324. GS_RIGID_BODY_STATE_DYNAMIC = 0x040,
  325. GS_RIGID_BODY_STATE_KINEMATIC = 0x080,
  326. GS_RIGID_BODY_STATE_LOCK_AXIS_X = 0x100,
  327. GS_RIGID_BODY_STATE_LOCK_AXIS_Y = 0x200,
  328. GS_RIGID_BODY_STATE_LOCK_AXIS_Z = 0x400
  329. } gs_rigid_body_state_flags;
  330. typedef struct gs_rigid_body_t {
  331. EMPTY_VAR();
  332. float mass;
  333. float inverve_mass;
  334. gs_vec3 linear_velocity;
  335. gs_vec3 angular_velocity;
  336. gs_vec3 force;
  337. gs_vec3 torque;
  338. gs_quat rotation;
  339. gs_vec3 local_center;
  340. gs_vec3 world_center;
  341. float sleep_time;
  342. float gravity_scale;
  343. uint32_t flags;
  344. uint32_t island_index;
  345. void * user_data;
  346. } gs_rigid_body_t;
  347. typedef struct gs_rigid_body_desc_t {
  348. EMPTY_VAR();
  349. } gs_rigid_body_desc_t;
  350. /* Collision Shape */
  351. typedef struct gs_collision_shape_t {
  352. EMPTY_VAR();
  353. } gs_collision_shape_t;
  354. typedef struct gs_contact_constraint_t {
  355. EMPTY_VAR();
  356. } gs_contact_constraint_t;
  357. typedef struct gs_raycast_data_t {
  358. EMPTY_VAR();
  359. } gs_raycast_data_t;
  360. // The listener is used to gather information about two shapes colliding. Physics objects created in these callbacks
  361. // Are not reported until following frame. Callbacks can be called quite frequently, so make them efficient.
  362. typedef struct gs_contact_listener_t {
  363. void (* begin_contact)(const gs_contact_constraint_t*);
  364. void (* end_contact)(const gs_contact_constraint_t*);
  365. } gs_contact_listener_t;
  366. typedef struct gs_query_callback_t {
  367. bool (* report_shape)(gs_collision_shape_t* shape);
  368. } gs_query_callback_t;
  369. // Contact Manager
  370. typedef struct gs_physics_contact_manager_t {
  371. EMPTY_VAR();
  372. } gs_physics_contact_manager_t;
  373. /* Physics Scene */
  374. typedef struct gs_physics_scene_t {
  375. gs_physics_contact_manager_t contact_manager;
  376. gs_paged_allocator_t paged_allocator;
  377. gs_stack_allocator_t stack_allocator;
  378. gs_heap_allocator_t heap_allocator;
  379. gs_vec3 gravity;
  380. float delta_time;
  381. uint32_t iterations;
  382. } gs_physics_scene_t;
  383. GS_API_DECL gs_physics_scene_t gs_physics_scene_new();
  384. GS_API_DECL void gs_physics_scene_step(gs_physics_scene_t* scene);
  385. GS_API_DECL uint32_t gs_physics_scene_create_body(gs_physics_scene_t* scene, gs_rigid_body_desc_t* desc);
  386. GS_API_DECL void gs_physics_scene_destroy_body(gs_physics_scene_t* scene, uint32_t id);
  387. GS_API_DECL void gs_physics_scene_destroy_all_bodies(gs_physics_scene_t* scene);
  388. GS_API_DECL gs_raycast_data_t gs_physics_scene_raycast(gs_physics_scene_t* scene, gs_query_callback_t* cb);
  389. /*
  390. Scene
  391. Contact Manager
  392. Collision Solver
  393. Dynamics Engine
  394. Rigid Body
  395. Collision Shape
  396. */
  397. /** @} */ // end of gs_physics_util
  398. /*==== Implementation ====*/
  399. #ifdef GS_PHYSICS_IMPL
  400. // Includes
  401. #ifndef GS_PHYSICS_NO_CCD
  402. #include "../external/ccd/libccd.c"
  403. #endif
  404. /*==== Support Functions =====*/
  405. // Poly
  406. GS_API_DECL void gs_support_poly(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  407. {
  408. const gs_poly_t* p = (gs_poly_t*)_o;
  409. // Bring direction vector into rotation space
  410. gs_quat qinv = gs_quat_inverse(xform->rotation);
  411. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  412. // Iterate over all points, find dot farthest in direction of d
  413. double max_dot, dot = 0.0;
  414. max_dot = (double)-FLT_MAX;
  415. for (uint32_t i = 0; i < p->cnt; i++)
  416. {
  417. dot = (double)gs_vec3_dot(d, p->verts[i]);
  418. if (dot > max_dot) {
  419. *out = p->verts[i];
  420. max_dot = dot;
  421. }
  422. }
  423. // Transform support point by rotation and translation of object
  424. *out = gs_quat_rotate(xform->rotation, *out);
  425. *out = gs_vec3_mul(xform->scale, *out);
  426. *out = gs_vec3_add(xform->position, *out);
  427. }
  428. // Sphere
  429. GS_API_DECL void gs_support_sphere(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  430. {
  431. // Support function is made according to Gino van den Bergen's paper
  432. // A Fast and Robust CCD Implementation for Collision Detection of
  433. // Convex Objects
  434. const gs_sphere_t* s = (gs_sphere_t*)_o;
  435. float scl = gs_max(xform->scale.x, gs_max(xform->scale.z, xform->scale.y));
  436. *out = gs_vec3_add(gs_vec3_scale(gs_vec3_norm(*dir), scl * s->r), gs_vec3_add(xform->position, s->c));
  437. }
  438. // Ray
  439. GS_API_DECL void gs_support_ray(const void* _r, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  440. {
  441. const gs_ray_t* r = (gs_ray_t*)_r;
  442. // Bring direction vector into rotation space
  443. gs_quat qinv = gs_quat_inverse(xform->rotation);
  444. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  445. gs_vec3 rs = r->p;
  446. gs_vec3 re = gs_vec3_add(r->p, gs_vec3_scale(r->d, r->len));
  447. if (gs_vec3_dot(rs, d) > gs_vec3_dot(re, d)) {
  448. *out = rs;
  449. } else {
  450. *out = re;
  451. }
  452. // Transform support point by rotation and translation of object
  453. *out = gs_quat_rotate(xform->rotation, *out);
  454. *out = gs_vec3_mul(xform->scale, *out);
  455. *out = gs_vec3_add(xform->position, *out);
  456. }
  457. // AABB
  458. GS_API_DECL void gs_support_aabb(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  459. {
  460. const gs_aabb_t* a = (gs_aabb_t*)_o;
  461. // Bring direction vector into rotation space
  462. gs_quat qinv = gs_quat_inverse(xform->rotation);
  463. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  464. // Compute half coordinates and sign for aabb (scale by transform)
  465. const float hx = (a->max.x - a->min.x) * 0.5f * xform->scale.x;
  466. const float hy = (a->max.y - a->min.y) * 0.5f * xform->scale.y;
  467. const float hz = (a->max.z - a->min.z) * 0.5f * xform->scale.z;
  468. gs_vec3 s = gs_vec3_sign(d);
  469. // Compure support for aabb
  470. *out = gs_v3(s.x * hx, s.y * hy, s.z * hz);
  471. // Transform support point by rotation and translation of object
  472. *out = gs_quat_rotate(xform->rotation, *out);
  473. *out = gs_vec3_add(xform->position, *out);
  474. }
  475. // Cylinder
  476. GS_API_DECL void gs_support_cylinder(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  477. {
  478. // Support function is made according to Gino van den Bergen's paper
  479. // A Fast and Robust CCD Implementation for Collision Detection of
  480. // Convex Objects
  481. const gs_cylinder_t* c = (const gs_cylinder_t*)_o;
  482. // Bring direction vector into rotation space
  483. gs_quat qinv = gs_quat_inverse(xform->rotation);
  484. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  485. // Compute support point (cylinder is standing on y axis, half height at origin)
  486. double zdist = sqrt(d.x * d.x + d.z * d.z);
  487. double hh = (double)c->height * 0.5 * xform->scale.y;
  488. if (zdist == 0.0)
  489. {
  490. *out = gs_v3(0.0, gs_vec3_signY(d) * hh, 0.0);
  491. }
  492. else
  493. {
  494. double r = (double)c->r / zdist;
  495. *out = gs_v3(r * d.x * xform->scale.x, gs_vec3_signY(d) * hh, r * d.z * xform->scale.z);
  496. }
  497. // Transform support point into world space
  498. *out = gs_quat_rotate(xform->rotation, *out);
  499. *out = gs_vec3_add(gs_vec3_add(xform->position, c->base), *out);
  500. }
  501. // Capsule
  502. GS_API_DECL void gs_support_capsule(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  503. {
  504. const gs_capsule_t* c = (const gs_capsule_t*)_o;
  505. // Bring direction vector into rotation space
  506. gs_quat qinv = gs_quat_inverse(xform->rotation);
  507. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  508. // Compute support point (cone is standing on y axis, half height at origin)
  509. const float s = gs_max(xform->scale.x, xform->scale.z);
  510. *out = gs_vec3_scale(gs_vec3_norm(d), c->r * s);
  511. double hh = (double)c->height * 0.5 * xform->scale.y;
  512. if (gs_vec3_dot(d, GS_YAXIS) > 0.0) {
  513. out->y += hh;
  514. } else {
  515. out->y -= hh;
  516. }
  517. // Transform support point into world space
  518. *out = gs_quat_rotate(xform->rotation, *out);
  519. *out = gs_vec3_add(gs_vec3_add(xform->position, c->base), *out);
  520. }
  521. // Cone
  522. GS_API_DECL void gs_support_cone(const void* _o, const gs_vqs* xform, const gs_vec3* dir, gs_vec3* out)
  523. {
  524. const gs_cone_t* c = (const gs_cone_t*)_o;
  525. // Bring direction vector into rotation space
  526. gs_quat qinv = gs_quat_inverse(xform->rotation);
  527. gs_vec3 d = gs_quat_rotate(qinv, *dir);
  528. // Compute support point (cone is standing on y axis, half height at origin)
  529. double sin_angle = c->r / sqrt((double)c->r * (double)c->r + (double)c->height * (double)c->height);
  530. double hh = (double)c->height * 0.5 * xform->scale.y;
  531. double len = sqrt(gs_vec3_len2(d));
  532. if (d.y > len * sin_angle)
  533. {
  534. *out = gs_v3(0.0f, (float)hh, 0.0f);
  535. }
  536. else
  537. {
  538. double s = sqrt(d.x * d.x + d.z * d.z);
  539. if (s > (double)GS_GJK_EPSILON)
  540. {
  541. double _d = (double)c->r / s;
  542. *out = gs_v3(d.x * _d * xform->scale.x, (float)-hh, d.z * _d * xform->scale.z);
  543. }
  544. else
  545. {
  546. *out = gs_v3(0.0, (float)-hh, 0.0);
  547. }
  548. }
  549. // Transform support point into world space
  550. *out = gs_quat_rotate(xform->rotation, *out);
  551. *out = gs_vec3_add(gs_vec3_add(xform->position, c->base), *out);
  552. }
  553. /*==== Collision Shapes ====*/
  554. /* Line/Segment */
  555. GS_API_DECL gs_line_t gs_line_closest_line(const gs_line_t* l, gs_vec3 p)
  556. {
  557. gs_vec3 cp = gs_line_closest_point(l, p);
  558. return gs_line(p, cp);
  559. }
  560. GS_API_DECL gs_vec3 gs_line_closest_point(const gs_line_t* l, gs_vec3 p)
  561. {
  562. gs_vec3 pt = gs_default_val();
  563. gs_vec3 ab = gs_vec3_sub(l->b, l->a);
  564. gs_vec3 pa = gs_vec3_sub(p, l->a);
  565. float t = gs_vec3_dot(pa, ab) / gs_vec3_dot(ab, ab);
  566. t = gs_clamp(t, 0.f, 1.f);
  567. pt = gs_vec3_add(l->a, gs_vec3_scale(ab, t));
  568. return pt;
  569. }
  570. GS_API_DECL gs_vec3 gs_line_direction(const gs_line_t* l)
  571. {
  572. return gs_vec3_norm(gs_vec3_sub(l->b, l->a));
  573. }
  574. /* Plane */
  575. // Modified from: https://graphics.stanford.edu/~mdfisher/Code/Engine/Plane.cpp.html
  576. GS_API_DECL gs_plane_t gs_plane_from_pt_normal(gs_vec3 pt, gs_vec3 n)
  577. {
  578. gs_plane_t p = gs_default_val();
  579. gs_vec3 nn = gs_vec3_norm(n);
  580. p.a = nn.x; p.b = nn.y; p.c = nn.z;
  581. p.d = -gs_vec3_dot(pt, nn);
  582. return p;
  583. }
  584. GS_API_DECL gs_plane_t gs_plane_from_pts(gs_vec3 a, gs_vec3 b, gs_vec3 c)
  585. {
  586. gs_vec3 n = gs_vec3_norm(gs_vec3_cross(gs_vec3_sub(b, a), gs_vec3_sub(c, a)));
  587. return gs_plane_from_pt_normal(a, n);
  588. }
  589. GS_API_DECL gs_vec3 gs_plane_normal(const gs_plane_t* p)
  590. {
  591. return gs_vec3_norm(gs_v3(p->a, p->b, p->c));
  592. }
  593. GS_API_DECL gs_vec3 gs_plane_closest_point(const gs_plane_t* p, gs_vec3 pt)
  594. {
  595. return gs_vec3_sub(pt, gs_vec3_scale(gs_plane_normal(p), gs_plane_signed_distance(p, pt)));
  596. }
  597. GS_API_DECL float gs_plane_signed_distance(const gs_plane_t* p, gs_vec3 pt)
  598. {
  599. return (p->a * pt.x + p->b * pt.y + p->c * pt.z + p->d);
  600. }
  601. GS_API_DECL float gs_plane_unsigned_distance(const gs_plane_t* p, gs_vec3 pt)
  602. {
  603. return fabsf(gs_plane_signed_distance(p, pt));
  604. }
  605. GS_API_DECL gs_plane_t gs_plane_normalized(const gs_plane_t* p)
  606. {
  607. gs_plane_t pn = gs_default_val();
  608. float d = sqrtf(p->a * p->a + p->b * p->b + p->c * p->c);
  609. pn.a = p->a / d; pn.b = p->b / d; pn.c = p->c / d; pn.d = p->d / d;
  610. return pn;
  611. }
  612. GS_API_DECL int32_t gs_plane_vs_sphere(const gs_plane_t* a, gs_vqs* xform_a, const gs_sphere_t* b, gs_vqs* xform_b, struct gs_contact_info_t* res)
  613. {
  614. // Cache necesary transforms, matrices
  615. gs_mat4 mat = xform_a ? gs_vqs_to_mat4(xform_a) : gs_mat4_identity();
  616. gs_mat4 inv = xform_a ? gs_mat4_inverse(mat) : gs_mat4_identity();
  617. gs_vqs local = gs_vqs_relative_transform(xform_a, xform_b);
  618. // Transform sphere center into local cone space
  619. gs_vec3 sc = xform_a ? gs_mat4_mul_vec3(inv, xform_b ? gs_vec3_add(xform_b->position, b->c) : b->c) : b->c;
  620. // Determine closest point from sphere center to plane
  621. gs_vec3 cp = gs_plane_closest_point(a, sc);
  622. // Determine if sphere is intersecting this point
  623. float sb = xform_b ? gs_max(local.scale.x, gs_max(local.scale.y, local.scale.z)) : 1.f;
  624. gs_vec3 dir = gs_vec3_sub(cp, sc);
  625. gs_vec3 n = gs_vec3_norm(dir);
  626. float d = gs_vec3_len(dir);
  627. float r = sb * b->r;
  628. if (d > r)
  629. {
  630. return false;
  631. }
  632. // Construct contact information
  633. if (res)
  634. {
  635. res->hit = true;
  636. res->depth = (r - d);
  637. res->normal = gs_mat4_mul_vec3(mat, n);
  638. res->point = gs_mat4_mul_vec3(mat, cp);
  639. }
  640. return true;
  641. }
  642. /* Ray */
  643. /* Frustum */
  644. /* Hit */
  645. #define _GS_COLLIDE_FUNC_IMPL(_TA, _TB, _F0, _F1)\
  646. GS_API_DECL int32_t gs_##_TA##_vs_##_TB(const gs_##_TA##_t* a, const gs_vqs* xa, const gs_##_TB##_t* b, const gs_vqs* xb, gs_contact_info_t* r)\
  647. {\
  648. return _gs_ccd_gjk_internal(a, xa, (_F0), b, xb, (_F1), r);\
  649. }
  650. /* Sphere */
  651. _GS_COLLIDE_FUNC_IMPL(sphere, sphere, gs_support_sphere, gs_support_sphere); // Sphere vs. Sphere
  652. _GS_COLLIDE_FUNC_IMPL(sphere, cylinder, gs_support_sphere, gs_support_cylinder); // Sphere vs. Cylinder
  653. _GS_COLLIDE_FUNC_IMPL(sphere, cone, gs_support_sphere, gs_support_cone); // Sphere vs. Cone
  654. _GS_COLLIDE_FUNC_IMPL(sphere, aabb, gs_support_sphere, gs_support_aabb); // Sphere vs. AABB
  655. _GS_COLLIDE_FUNC_IMPL(sphere, capsule, gs_support_sphere, gs_support_capsule); // Sphere vs. Capsule
  656. _GS_COLLIDE_FUNC_IMPL(sphere, poly, gs_support_sphere, gs_support_poly); // Sphere vs. Poly
  657. _GS_COLLIDE_FUNC_IMPL(sphere, ray, gs_support_sphere, gs_support_ray); // Sphere vs. Ray
  658. /* AABB */
  659. _GS_COLLIDE_FUNC_IMPL(aabb, aabb, gs_support_aabb, gs_support_aabb); // AABB vs. AABB
  660. _GS_COLLIDE_FUNC_IMPL(aabb, cylinder, gs_support_aabb, gs_support_cylinder); // AABB vs. Cylinder
  661. _GS_COLLIDE_FUNC_IMPL(aabb, cone, gs_support_aabb, gs_support_cone); // AABB vs. Cone
  662. _GS_COLLIDE_FUNC_IMPL(aabb, sphere, gs_support_aabb, gs_support_sphere); // AABB vs. Sphere
  663. _GS_COLLIDE_FUNC_IMPL(aabb, capsule, gs_support_aabb, gs_support_capsule); // AABB vs. Capsule
  664. _GS_COLLIDE_FUNC_IMPL(aabb, poly, gs_support_aabb, gs_support_poly); // AABB vs. Poly
  665. _GS_COLLIDE_FUNC_IMPL(aabb, ray, gs_support_aabb, gs_support_ray); // AABB vs. Ray
  666. /* Capsule */
  667. _GS_COLLIDE_FUNC_IMPL(capsule, capsule, gs_support_capsule, gs_support_capsule); // Capsule vs. Capsule
  668. _GS_COLLIDE_FUNC_IMPL(capsule, cylinder, gs_support_capsule, gs_support_cylinder); // Capsule vs. Cylinder
  669. _GS_COLLIDE_FUNC_IMPL(capsule, cone, gs_support_capsule, gs_support_cone); // Capsule vs. Cone
  670. _GS_COLLIDE_FUNC_IMPL(capsule, sphere, gs_support_capsule, gs_support_sphere); // Capsule vs. Sphere
  671. _GS_COLLIDE_FUNC_IMPL(capsule, aabb, gs_support_capsule, gs_support_aabb); // Capsule vs. AABB
  672. _GS_COLLIDE_FUNC_IMPL(capsule, poly, gs_support_capsule, gs_support_poly); // Capsule vs. Poly
  673. _GS_COLLIDE_FUNC_IMPL(capsule, ray, gs_support_capsule, gs_support_ray); // Capsule vs. Ray
  674. /* Poly */
  675. _GS_COLLIDE_FUNC_IMPL(poly, poly, gs_support_poly, gs_support_poly); // Poly vs. Poly
  676. _GS_COLLIDE_FUNC_IMPL(poly, cylinder, gs_support_poly, gs_support_cylinder); // Poly vs. Cylinder
  677. _GS_COLLIDE_FUNC_IMPL(poly, cone, gs_support_poly, gs_support_cone); // Poly vs. Cone
  678. _GS_COLLIDE_FUNC_IMPL(poly, sphere, gs_support_poly, gs_support_sphere); // Poly vs. Sphere
  679. _GS_COLLIDE_FUNC_IMPL(poly, aabb, gs_support_poly, gs_support_aabb); // Poly vs. AABB
  680. _GS_COLLIDE_FUNC_IMPL(poly, capsule, gs_support_poly, gs_support_capsule); // Poly vs. Capsule
  681. _GS_COLLIDE_FUNC_IMPL(poly, ray, gs_support_poly, gs_support_ray); // Poly vs. Ray
  682. /* Cylinder */
  683. _GS_COLLIDE_FUNC_IMPL(cylinder, cylinder, gs_support_cylinder, gs_support_cylinder); // Cylinder vs. Cylinder
  684. _GS_COLLIDE_FUNC_IMPL(cylinder, poly, gs_support_poly, gs_support_poly); // Cylinder vs. Poly
  685. _GS_COLLIDE_FUNC_IMPL(cylinder, cone, gs_support_cylinder, gs_support_cone); // Cylinder vs. Cone
  686. _GS_COLLIDE_FUNC_IMPL(cylinder, sphere, gs_support_cylinder, gs_support_sphere); // Cylinder vs. Sphere
  687. _GS_COLLIDE_FUNC_IMPL(cylinder, aabb, gs_support_cylinder, gs_support_aabb); // Cylinder vs. AABB
  688. _GS_COLLIDE_FUNC_IMPL(cylinder, capsule, gs_support_cylinder, gs_support_capsule); // Cylinder vs. Capsule
  689. _GS_COLLIDE_FUNC_IMPL(cylinder, ray, gs_support_cylinder, gs_support_ray); // Cylinder vs. Ray
  690. /* Cone */
  691. _GS_COLLIDE_FUNC_IMPL(cone, cone, gs_support_cone, gs_support_cone); // Cone vs. Cone
  692. _GS_COLLIDE_FUNC_IMPL(cone, poly, gs_support_poly, gs_support_poly); // Cone vs. Poly
  693. _GS_COLLIDE_FUNC_IMPL(cone, cylinder, gs_support_cone, gs_support_cylinder); // Cone vs. Cylinder
  694. _GS_COLLIDE_FUNC_IMPL(cone, sphere, gs_support_cone, gs_support_sphere); // Cone vs. Sphere
  695. _GS_COLLIDE_FUNC_IMPL(cone, aabb, gs_support_cone, gs_support_aabb); // Cone vs. AABB
  696. _GS_COLLIDE_FUNC_IMPL(cone, capsule, gs_support_cone, gs_support_capsule); // Cone vs. Capsule
  697. _GS_COLLIDE_FUNC_IMPL(cone, ray, gs_support_cone, gs_support_ray); // Cone vs. Ray
  698. /*==== GKJ ====*/
  699. // Need 2D GJK/EPA impl in external (modify from chipmunk 2d)
  700. // Internal functions
  701. /*
  702. bool gs_gjk_check_if_simplex_contains_origin(gs_gjk_simplex_t* simplex, gs_vec3* search_dir, gs_gjk_dimension dimension);
  703. void gs_gjk_simplex_push(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p);
  704. void gs_gjk_simplex_push_back(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p);
  705. void gs_gjk_simplex_push_front(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p);
  706. void gs_gjk_simplex_insert(gs_gjk_simplex_t* simplex, uint32_t idx, gs_gjk_support_point_t p);
  707. void gs_gjk_bary(gs_vec3 p, gs_vec3 a, gs_vec3 b, gs_vec3 c, float* u, float* v, float* w);
  708. // gs_gjk_epa_edge_t gs_gjk_epa_find_closest_edge(gs_gjk_simplex_t* simplex);
  709. gs_gjk_support_point_t gs_gjk_generate_support_point(const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1, gs_vec3 dir);
  710. gs_gjk_epa_edge_t gs_gjk_epa_find_closest_edge(gs_dyn_array(gs_gjk_support_point_t) polytope);
  711. // Modified from: https://github.com/Nightmask3/Physics-Framework/blob/master/PhysicsFramework/PhysicsManager.cpp
  712. int32_t gs_gjk(const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1, gs_gjk_dimension dimension, gs_contact_info_t* res)
  713. {
  714. // Simplex simplex;
  715. gs_gjk_simplex_t simplex = gs_default_val();
  716. gs_vec3 search_dir = gs_v3s(1.f);
  717. gs_gjk_support_point_t new_pt = gs_gjk_generate_support_point(ci0, ci1, search_dir);
  718. // Stability check
  719. if (gs_vec3_dot(search_dir, new_pt.minkowski_hull_vert) >= gs_vec3_len(new_pt.minkowski_hull_vert) * 0.8f)
  720. {
  721. // the chosen direction is invalid, will produce (0,0,0) for a subsequent direction later
  722. search_dir = gs_v3(0.f, 1.f, 0.f);
  723. new_pt = gs_gjk_generate_support_point(ci0, ci1, search_dir);
  724. }
  725. gs_gjk_simplex_push(&simplex, new_pt);
  726. // Invert the search direction for the next point
  727. search_dir = gs_vec3_neg(search_dir);
  728. uint32_t iterationCount = 0;
  729. while (true)
  730. {
  731. if (iterationCount++ >= GS_GJK_MAX_ITERATIONS)
  732. return false;
  733. // Stability check
  734. // Error, for some reason the direction vector is broken
  735. if (gs_vec3_len(search_dir) <= 0.0001f)
  736. return false;
  737. // Add a new point to the simplex
  738. gs_gjk_support_point_t new_pt = gs_gjk_generate_support_point(ci0, ci1, search_dir);
  739. gs_gjk_simplex_push(&simplex, new_pt);
  740. // If projection of newly added point along the search direction has not crossed the origin,
  741. // the Minkowski Difference could not contain the origin, objects are not colliding
  742. if (gs_vec3_dot(new_pt.minkowski_hull_vert, search_dir) < 0.0f)
  743. {
  744. return false;
  745. }
  746. else
  747. {
  748. // If the new point IS past the origin, check if the simplex contains the origin,
  749. // If it doesn't modify search direction to point towards to origin
  750. if (gs_gjk_check_if_simplex_contains_origin(&simplex, &search_dir, dimension))
  751. {
  752. // Capture collision data using EPA if requested by user
  753. if (res)
  754. {
  755. switch (dimension) {
  756. case GS_GJK_DIMENSION_3D: *res = gs_gjk_epa(&simplex, ci0, ci1); break;
  757. case GS_GJK_DIMENSION_2D: *res = gs_gjk_epa_2d(&simplex, ci0, ci1); break;
  758. }
  759. return res->hit;
  760. }
  761. else
  762. {
  763. return true;
  764. }
  765. }
  766. }
  767. }
  768. }
  769. GS_API_DECL gs_gjk_support_point_t gs_gjk_generate_support_point(const gs_gjk_collider_info_t* ci0, const gs_gjk_collider_info_t* ci1, gs_vec3 dir)
  770. {
  771. gs_gjk_support_point_t sp = {0};
  772. sp.support_a = ci0->func(ci0->collider, ci0->xform, dir);
  773. sp.support_b = ci1->func(ci1->collider, ci1->xform, gs_vec3_neg(dir));
  774. sp.minkowski_hull_vert = gs_vec3_sub(sp.support_a, sp.support_b);
  775. return sp;
  776. }
  777. // Closest point method taken from Erin Catto's GDC 2010 slides
  778. // Returns the closest point
  779. gs_vec3 gs_closest_point_on_line_from_target_point(gs_line_t line, gs_vec3 point, float* u, float* v)
  780. {
  781. gs_vec3 line_seg = gs_vec3_sub(line.b, line.a);
  782. gs_vec3 normalized = gs_vec3_norm(line_seg);
  783. *v = gs_vec3_dot(gs_vec3_neg(line.a), normalized) / gs_vec3_len(line_seg);
  784. *u = gs_vec3_dot(line.b, normalized) / gs_vec3_len(line_seg);
  785. gs_vec3 closest_point;
  786. if (*u <= 0.0f)
  787. {
  788. closest_point = line.b;
  789. }
  790. else if (*v <= 0.0f)
  791. {
  792. closest_point = line.a;
  793. }
  794. else
  795. {
  796. closest_point = gs_vec3_add(gs_vec3_scale(line.a, *u), gs_vec3_scale(line.b, *v));
  797. }
  798. return closest_point;
  799. }
  800. void gs_gjk_simplex_push(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p)
  801. {
  802. simplex->ct = gs_min(simplex->ct + 1, 4);
  803. for (int32_t i = simplex->ct - 1; i > 0; i--)
  804. simplex->points[i] = simplex->points[i - 1];
  805. simplex->points[0] = p;
  806. }
  807. void gs_gjk_simplex_push_back(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p)
  808. {
  809. if (simplex->ct >= 4) return;
  810. simplex->ct = gs_min(simplex->ct + 1, 4);
  811. simplex->points[simplex->ct - 1] = p;
  812. }
  813. void gs_gjk_simplex_push_front(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t p)
  814. {
  815. if (simplex->ct == 3) {
  816. simplex->points[3] = simplex->points[2];
  817. simplex->points[2] = simplex->points[1];
  818. simplex->points[1] = simplex->points[0];
  819. simplex->points[0] = p;
  820. }
  821. else if (simplex->ct == 2) {
  822. simplex->points[2] = simplex->points[1];
  823. simplex->points[1] = simplex->points[0];
  824. simplex->points[0] = p;
  825. }
  826. simplex->ct = gs_min(simplex->ct + 1, 4);
  827. }
  828. void gs_gjk_simplex_insert(gs_gjk_simplex_t* simplex, uint32_t idx, gs_gjk_support_point_t p)
  829. {
  830. // Need more points (this is where polytope comes into play, I think...)
  831. // Splice the simplex by index
  832. if (idx > 4) return;
  833. simplex->ct = gs_min(simplex->ct + 1, 4);
  834. for (int32_t i = simplex->ct - 1; i > idx; i--)
  835. simplex->points[i] = simplex->points[i - 1];
  836. simplex->points[idx] = p;
  837. }
  838. void gs_gjk_simplex_clear(gs_gjk_simplex_t* simplex)
  839. {
  840. simplex->ct = 0;
  841. }
  842. void gs_gjk_simplex_set1(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t a)
  843. {
  844. simplex->ct = 1;
  845. simplex->a = a;
  846. }
  847. void gs_gjk_simplex_set2(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t a, gs_gjk_support_point_t b)
  848. {
  849. simplex->ct = 2;
  850. simplex->a = a;
  851. simplex->b = b;
  852. }
  853. void gs_gjk_simplex_set3(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t a, gs_gjk_support_point_t b, gs_gjk_support_point_t c)
  854. {
  855. simplex->ct = 3;
  856. simplex->a = a;
  857. simplex->b = b;
  858. simplex->c = c;
  859. }
  860. void gs_gjk_simplex_set4(gs_gjk_simplex_t* simplex, gs_gjk_support_point_t a, gs_gjk_support_point_t b, gs_gjk_support_point_t c, gs_gjk_support_point_t d)
  861. {
  862. simplex->ct = 4;
  863. simplex->a = a;
  864. simplex->b = b;
  865. simplex->c = c;
  866. simplex->d = d;
  867. }
  868. bool gs_gjk_check_if_simplex_contains_origin(gs_gjk_simplex_t* simplex, gs_vec3* search_dir, gs_gjk_dimension dimension)
  869. {
  870. // Line case
  871. if (simplex->ct == 2)
  872. {
  873. // Line cannot contain the origin, only search for the direction to it
  874. gs_vec3 new_point_to_old_point = gs_vec3_sub(simplex->b.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  875. gs_vec3 new_point_to_origin = gs_vec3_neg(simplex->a.minkowski_hull_vert);
  876. // Method given by Erin Catto in GDC 2010 presentation
  877. float u = 0.0f, v = 0.0f;
  878. gs_line_t line = gs_line(simplex->a.minkowski_hull_vert, simplex->b.minkowski_hull_vert);
  879. gs_vec3 origin = gs_v3s(0.f);
  880. gs_vec3 closest_point = gs_closest_point_on_line_from_target_point(line, origin, &u, &v);
  881. // Test vertex region of new simplex point first as highest chance to be there
  882. if (v <= 0.0f)
  883. {
  884. gs_gjk_simplex_set1(simplex, simplex->a);
  885. *search_dir = gs_vec3_neg(closest_point);
  886. return false;
  887. }
  888. else if (u <= 0.0f)
  889. {
  890. gs_gjk_simplex_set1(simplex, simplex->b);
  891. *search_dir = gs_vec3_neg(closest_point);
  892. return false;
  893. }
  894. else
  895. {
  896. *search_dir = gs_vec3_neg(closest_point);
  897. return false;
  898. }
  899. }
  900. // Triangle case
  901. else if (simplex->ct == 3)
  902. {
  903. // Find the newly added features
  904. gs_vec3 new_point_to_origin = gs_vec3_neg(simplex->a.minkowski_hull_vert);
  905. gs_vec3 edge1 = gs_vec3_sub(simplex->b.minkowski_hull_vert, simplex->a.minkowski_hull_vert); // AB
  906. gs_vec3 edge2 = gs_vec3_sub(simplex->c.minkowski_hull_vert, simplex->a.minkowski_hull_vert); // AC
  907. // Find the normals to the triangle and the two edges
  908. gs_vec3 triangle_normal = gs_vec3_cross(edge1, edge2); // ABC
  909. gs_vec3 edge1_normal = gs_vec3_cross(edge1, triangle_normal);
  910. gs_vec3 edge2_normal = gs_vec3_cross(triangle_normal, edge2);
  911. // If origin is closer to the area along the second edge normal (if same_dir(AB X ABC, -A))
  912. if (gs_vec3_dot(edge2_normal, new_point_to_origin) > 0.0f)
  913. {
  914. // If closer to the edge then find the normal that points towards the origin
  915. if (gs_vec3_dot(edge2, new_point_to_origin) > 0.0f)
  916. {
  917. // [AC]
  918. *search_dir = gs_vec3_triple_cross_product(edge2, new_point_to_origin, edge2);
  919. gs_gjk_simplex_clear(simplex);
  920. gs_gjk_simplex_set2(simplex, simplex->a, simplex->c);
  921. return false;
  922. }
  923. // If closer to the new simplex point
  924. else
  925. {
  926. // The "Star case" from the Muratori lecture
  927. // If new search direction should be along edge normal
  928. if (gs_vec3_dot(edge1, new_point_to_origin) > 0.0f)
  929. {
  930. // [AB]
  931. *search_dir = gs_vec3_triple_cross_product(edge1, new_point_to_origin, edge1);
  932. gs_gjk_simplex_clear(simplex);
  933. gs_gjk_simplex_set2(simplex, simplex->a, simplex->b);
  934. return false;
  935. }
  936. else // If new search direction should be along the new Simplex point
  937. {
  938. // Return new simplex point alone [A]
  939. *search_dir = new_point_to_origin;
  940. gs_gjk_simplex_clear(simplex);
  941. gs_gjk_simplex_set1(simplex, simplex->a);
  942. return false;
  943. }
  944. }
  945. }
  946. // In 2D, this is a "success" case, otherwise keep going for 3D
  947. else
  948. {
  949. // Max simplex dimension is a triangle
  950. if (dimension == GS_GJK_DIMENSION_2D)
  951. {
  952. return true;
  953. }
  954. // The "Star case" from the Muratori lecture
  955. // If closer to the first edge normal
  956. if (gs_vec3_dot(edge1_normal, new_point_to_origin) > 0.0f)
  957. {
  958. // If new search direction should be along edge normal
  959. if (gs_vec3_dot(edge1, new_point_to_origin) > 0.0f)
  960. {
  961. // Return it as [A, B]
  962. *search_dir = gs_vec3_triple_cross_product(edge1, new_point_to_origin, edge1);
  963. gs_gjk_simplex_clear(simplex);
  964. gs_gjk_simplex_set2(simplex, simplex->a, simplex->b);
  965. return false;
  966. }
  967. else // If new search direction should be along the new Simplex point
  968. {
  969. // Return new simplex point alone [A]
  970. *search_dir = new_point_to_origin;
  971. gs_gjk_simplex_clear(simplex);
  972. gs_gjk_simplex_set1(simplex, simplex->a);
  973. return false;
  974. }
  975. }
  976. else
  977. {
  978. // Check if it is above the triangle
  979. if (gs_vec3_dot(triangle_normal, new_point_to_origin) > 0.0f)
  980. {
  981. // No need to change the simplex, return as [A, B, C]
  982. *search_dir = triangle_normal;
  983. return false;
  984. }
  985. else // Has to be below the triangle, all 4 other possible regions checked
  986. {
  987. // Return simplex as [A, C, B]
  988. *search_dir = gs_vec3_neg(triangle_normal);
  989. gs_gjk_simplex_set3(simplex, simplex->a, simplex->c, simplex->b);
  990. return false;
  991. }
  992. }
  993. }
  994. }
  995. // Tetrahedron for 3D case
  996. else if (simplex->ct == 4)
  997. {
  998. // the simplex is a tetrahedron, must check if it is outside any of the side triangles,
  999. // if it is then set the simplex equal to that triangle and continue, otherwise we know
  1000. // there is an intersection and exit
  1001. gs_vec3 edge1 = gs_vec3_sub(simplex->b.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1002. gs_vec3 edge2 = gs_vec3_sub(simplex->c.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1003. gs_vec3 edge3 = gs_vec3_sub(simplex->d.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1004. gs_vec3 face1_normal = gs_vec3_cross(edge1, edge2);
  1005. gs_vec3 face2_normal = gs_vec3_cross(edge2, edge3);
  1006. gs_vec3 face3_normal = gs_vec3_cross(edge3, edge1);
  1007. gs_vec3 new_point_to_origin = gs_vec3_neg(simplex->a.minkowski_hull_vert);
  1008. bool contains = true;
  1009. if (gs_vec3_dot(face1_normal, new_point_to_origin) > 0.0f)
  1010. {
  1011. // Origin is in front of first face, simplex is correct already
  1012. // goto tag;
  1013. contains = false;
  1014. }
  1015. if (!contains && gs_vec3_dot(face2_normal, new_point_to_origin) > 0.0f)
  1016. {
  1017. // Origin is in front of second face, simplex is set to this triangle [A, C, D]
  1018. gs_gjk_simplex_clear(simplex);
  1019. gs_gjk_simplex_set3(simplex, simplex->a, simplex->c, simplex->d);
  1020. contains = false;
  1021. }
  1022. if (!contains && gs_vec3_dot(face3_normal, new_point_to_origin) > 0.0f)
  1023. {
  1024. // Origin is in front of third face, simplex is set to this triangle [A, D, B]
  1025. gs_gjk_simplex_clear(simplex);
  1026. gs_gjk_simplex_set3(simplex, simplex->a, simplex->d, simplex->b);
  1027. contains = false;
  1028. }
  1029. // If reached here it means the simplex MUST contain the origin, intersection confirmed
  1030. if (contains) {
  1031. return true;
  1032. }
  1033. gs_vec3 edge1_normal = gs_vec3_cross(edge1, face1_normal);
  1034. if (gs_vec3_dot(edge1_normal, new_point_to_origin) > 0.0f)
  1035. {
  1036. // Origin is along the normal of edge1, set the simplex to that edge [A, B]
  1037. *search_dir = gs_vec3_triple_cross_product(edge1, new_point_to_origin, edge1);
  1038. gs_gjk_simplex_clear(simplex);
  1039. gs_gjk_simplex_set2(simplex, simplex->a, simplex->b);
  1040. return false;
  1041. }
  1042. gs_vec3 edge2Normal = gs_vec3_cross(face1_normal, edge2);
  1043. if (gs_vec3_dot(edge2Normal, new_point_to_origin) > 0.0f)
  1044. {
  1045. // Origin is along the normal of edge2, set the simplex to that edge [A, C]
  1046. *search_dir = gs_vec3_triple_cross_product(edge2, new_point_to_origin, edge2);
  1047. gs_gjk_simplex_clear(simplex);
  1048. gs_gjk_simplex_set2(simplex, simplex->a, simplex->c);
  1049. return false;
  1050. }
  1051. // If reached here the origin is along the first face normal, set the simplex to this face [A, B, C]
  1052. *search_dir = face1_normal;
  1053. gs_gjk_simplex_clear(simplex);
  1054. gs_gjk_simplex_set3(simplex, simplex->a, simplex->b, simplex->c);
  1055. return false;
  1056. }
  1057. return false;
  1058. }
  1059. // Find barycentric coordinates of triangle with respect to p
  1060. GS_API_DECL void gs_gjk_bary(gs_vec3 p, gs_vec3 a, gs_vec3 b, gs_vec3 c, float* u, float* v, float* w)
  1061. {
  1062. gs_vec3 v0 = gs_vec3_sub(b, a), v1 = gs_vec3_sub(c, a), v2 = gs_vec3_sub(p, a);
  1063. float d00 = gs_vec3_dot(v0, v0);
  1064. float d01 = gs_vec3_dot(v0, v1);
  1065. float d11 = gs_vec3_dot(v1, v1);
  1066. float d20 = gs_vec3_dot(v2, v0);
  1067. float d21 = gs_vec3_dot(v2, v1);
  1068. float denom = d00 * d11 - d01 * d01;
  1069. *v = (d11 * d20 - d01 * d21) / denom;
  1070. *w = (d00 * d21 - d01 * d20) / denom;
  1071. *u = 1.0f - *v - *w;
  1072. }
  1073. //Expanding Polytope Algorithm
  1074. GS_API_DECL gs_contact_info_t gs_gjk_epa(
  1075. const gs_gjk_simplex_t* simplex,
  1076. const gs_gjk_collider_info_t* ci0,
  1077. const gs_gjk_collider_info_t* ci1
  1078. )
  1079. {
  1080. gs_contact_info_t res = {0};
  1081. // Cache pointers for collider 0
  1082. void* c0 = ci0->collider;
  1083. gs_gjk_support_func_t f0 = ci0->func;
  1084. gs_phys_xform_t* xform_0 = ci0->xform;
  1085. // Cache pointers for collider 1
  1086. void* c1 = ci1->collider;
  1087. gs_gjk_support_func_t f1 = ci1->func;
  1088. gs_phys_xform_t* xform_1 = ci1->xform;
  1089. // Array of polytope faces, each with 3 support points and a normal
  1090. gs_gjk_polytope_face_t faces[GS_EPA_MAX_NUM_FACES] = {0};
  1091. gs_vec3 bma = gs_vec3_sub(simplex->b.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1092. gs_vec3 cma = gs_vec3_sub(simplex->c.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1093. gs_vec3 dma = gs_vec3_sub(simplex->d.minkowski_hull_vert, simplex->a.minkowski_hull_vert);
  1094. gs_vec3 cmb = gs_vec3_sub(simplex->c.minkowski_hull_vert, simplex->b.minkowski_hull_vert);
  1095. gs_vec3 dmb = gs_vec3_sub(simplex->d.minkowski_hull_vert, simplex->b.minkowski_hull_vert);
  1096. faces[0] = gs_ctor(gs_gjk_polytope_face_t, {simplex->a, simplex->b, simplex->c}, gs_vec3_norm(gs_vec3_cross(bma, cma))); // ABC
  1097. faces[1] = gs_ctor(gs_gjk_polytope_face_t, {simplex->a, simplex->c, simplex->d}, gs_vec3_norm(gs_vec3_cross(cma, dma))); // ACD
  1098. faces[2] = gs_ctor(gs_gjk_polytope_face_t, {simplex->a, simplex->d, simplex->b}, gs_vec3_norm(gs_vec3_cross(dma, bma))); // ADB
  1099. faces[3] = gs_ctor(gs_gjk_polytope_face_t, {simplex->b, simplex->d, simplex->c}, gs_vec3_norm(gs_vec3_cross(dmb, cmb))); // BDC
  1100. int32_t num_faces = 4;
  1101. int32_t closest_face;
  1102. for (int32_t iterations = 0; iterations < GS_EPA_MAX_NUM_ITERATIONS; ++iterations)
  1103. {
  1104. //Find face that's closest to origin
  1105. float min_dist = gs_vec3_dot(faces[0].points[0].minkowski_hull_vert, faces[0].normal);
  1106. closest_face = 0;
  1107. for (int32_t i = 1; i < num_faces; ++i)
  1108. {
  1109. float dist = gs_vec3_dot(faces[i].points[0].minkowski_hull_vert, faces[i].normal);
  1110. if (dist < min_dist)
  1111. {
  1112. min_dist = dist;
  1113. closest_face = i;
  1114. }
  1115. }
  1116. // Search normal to face that's closest to origin
  1117. gs_vec3 search_dir = faces[closest_face].normal;
  1118. gs_gjk_support_point_t p = gs_gjk_generate_support_point(ci0, ci1, search_dir);
  1119. float depth = gs_vec3_dot(p.minkowski_hull_vert, search_dir);
  1120. // Within tolerance, so extract contact information from hull
  1121. if (depth - min_dist < GS_EPA_TOLERANCE)
  1122. {
  1123. // Cache local pointers
  1124. gs_gjk_polytope_face_t* f = &faces[closest_face];
  1125. gs_vec3* n = &f->normal;
  1126. gs_gjk_support_point_t* sp0 = &f->points[0];
  1127. gs_gjk_support_point_t* sp1 = &f->points[1];
  1128. gs_gjk_support_point_t* sp2 = &f->points[2];
  1129. gs_vec3* p0 = &sp0->minkowski_hull_vert;
  1130. gs_vec3* p1 = &sp1->minkowski_hull_vert;
  1131. gs_vec3* p2 = &sp2->minkowski_hull_vert;
  1132. // Normal and depth information
  1133. res.hit = true;
  1134. res.normal = gs_vec3_norm(*n);
  1135. res.depth = depth;
  1136. // Get barycentric coordinates of resulting triangle face
  1137. float u = 0.f, v = 0.f, w = 0.f;
  1138. gs_gjk_bary(*n, *p0, *p1, *p2, &u, &v, &w);
  1139. gs_vec3* support_0, *support_1, *support_2;
  1140. // A Contact points
  1141. support_0 = &sp0->support_a;
  1142. support_1 = &sp1->support_a;
  1143. support_2 = &sp2->support_a;
  1144. // Contact point on collider a
  1145. res.points[0] = gs_vec3_add(gs_vec3_add(gs_vec3_scale(*support_0, u), gs_vec3_scale(*support_1, v)), gs_vec3_scale(*support_2, w));
  1146. // B Contact points
  1147. support_0 = &sp0->support_b;
  1148. support_1 = &sp1->support_b;
  1149. support_2 = &sp2->support_b;
  1150. // Contact point on collider b
  1151. res.points[1] = gs_vec3_add(gs_vec3_add(gs_vec3_scale(*support_0, u), gs_vec3_scale(*support_1, v)), gs_vec3_scale(*support_2, w));
  1152. return res;
  1153. }
  1154. // Fix Edges
  1155. gs_gjk_support_point_t loose_edges[GS_EPA_MAX_NUM_LOOSE_EDGES][2];
  1156. int32_t num_loose_edges = 0;
  1157. // Find all triangles that are facing p
  1158. for (int32_t i = 0; i < num_faces; ++i)
  1159. {
  1160. // Grab direction from first point on face at p to i
  1161. gs_vec3 dir = gs_vec3_sub(p.minkowski_hull_vert, faces[i].points[0].minkowski_hull_vert);
  1162. // Triangle i faces p, remove it
  1163. if (gs_vec3_same_dir(faces[i].normal, dir))
  1164. {
  1165. // Add removed triangle's edges to loose edge list.
  1166. // If it's already there, remove it (both triangles it belonged to are gone)
  1167. for (int32_t j = 0; j < 3; ++j)
  1168. {
  1169. gs_gjk_support_point_t current_edge[2] = {faces[i].points[j], faces[i].points[(j + 1) % 3]};
  1170. bool found_edge = false;
  1171. for (int32_t k = 0; k < num_loose_edges; ++k) //Check if current edge is already in list
  1172. {
  1173. //Edge is already in the list, remove it
  1174. if (gs_vec3_eq(loose_edges[k][1].minkowski_hull_vert, current_edge[0].minkowski_hull_vert)
  1175. && gs_vec3_eq(loose_edges[k][0].minkowski_hull_vert, current_edge[1].minkowski_hull_vert))
  1176. {
  1177. // Overwrite current edge with last edge in list
  1178. loose_edges[k][0] = loose_edges[num_loose_edges - 1][0];
  1179. loose_edges[k][1] = loose_edges[num_loose_edges - 1][1];
  1180. num_loose_edges--;
  1181. // Exit loop because edge can only be shared once
  1182. found_edge = true;
  1183. k = num_loose_edges;
  1184. }
  1185. }
  1186. // Add current edge to list (is unique)
  1187. if (!found_edge)
  1188. {
  1189. if (num_loose_edges >= GS_EPA_MAX_NUM_LOOSE_EDGES) break;
  1190. loose_edges[num_loose_edges][0] = current_edge[0];
  1191. loose_edges[num_loose_edges][1] = current_edge[1];
  1192. num_loose_edges++;
  1193. }
  1194. }
  1195. // Remove triangle i from list
  1196. faces[i].points[0] = faces[num_faces - 1].points[0];
  1197. faces[i].points[1] = faces[num_faces - 1].points[1];
  1198. faces[i].points[2] = faces[num_faces - 1].points[2];
  1199. faces[i].normal = faces[num_faces - 1].normal;
  1200. num_faces--;
  1201. i--;
  1202. }
  1203. }
  1204. // Reconstruct polytope with p now added
  1205. for (int32_t i = 0; i < num_loose_edges; ++i)
  1206. {
  1207. if (num_faces >= GS_EPA_MAX_NUM_FACES) break;
  1208. faces[num_faces].points[0] = loose_edges[i][0];
  1209. faces[num_faces].points[1] = loose_edges[i][1];
  1210. faces[num_faces].points[2] = p;
  1211. gs_vec3 zmo = gs_vec3_sub(loose_edges[i][0].minkowski_hull_vert, loose_edges[i][1].minkowski_hull_vert);
  1212. gs_vec3 zmp = gs_vec3_sub(loose_edges[i][0].minkowski_hull_vert, p.minkowski_hull_vert);
  1213. faces[num_faces].normal = gs_vec3_norm(gs_vec3_cross(zmo, zmp));
  1214. //Check for wrong normal to maintain CCW winding
  1215. // In case dot result is only slightly < 0 (because origin is on face)
  1216. float bias = 0.000001;
  1217. if (gs_vec3_dot(faces[num_faces].points[0].minkowski_hull_vert, faces[num_faces].normal) + bias < 0.f){
  1218. gs_gjk_support_point_t temp = faces[num_faces].points[0];
  1219. faces[num_faces].points[0] = faces[num_faces].points[1];
  1220. faces[num_faces].points[1] = temp;
  1221. faces[num_faces].normal = gs_vec3_scale(faces[num_faces].normal, -1.f);
  1222. }
  1223. num_faces++;
  1224. }
  1225. }
  1226. // Return most recent closest point
  1227. float dot = gs_vec3_dot(faces[closest_face].points[0].minkowski_hull_vert, faces[closest_face].normal);
  1228. gs_vec3 norm = gs_vec3_scale(faces[closest_face].normal, dot);
  1229. res.hit = false;
  1230. res.normal = gs_vec3_norm(norm);
  1231. res.depth = gs_vec3_len(norm);
  1232. return res;
  1233. }
  1234. // Expanding Polytope Algorithm 2D
  1235. GS_API_DECL gs_contact_info_t gs_gjk_epa_2d(
  1236. const gs_gjk_simplex_t* simplex,
  1237. const gs_gjk_collider_info_t* ci0,
  1238. const gs_gjk_collider_info_t* ci1
  1239. )
  1240. {
  1241. gs_dyn_array(gs_gjk_support_point_t) polytope = NULL;
  1242. gs_contact_info_t res = gs_default_val();
  1243. gs_gjk_support_point_t p = gs_default_val();
  1244. // Copy over simplex into polytope array
  1245. for (uint32_t i = 0; i < simplex->ct; ++i) {
  1246. gs_dyn_array_push(polytope, simplex->points[i]);
  1247. }
  1248. // p = gs_gjk_generate_support_point(ci0, ci1, gs_v3s(1.f));
  1249. // gs_gjk_simplex_push_front(simplex, p);
  1250. gs_gjk_epa_edge_t e = gs_default_val();
  1251. uint32_t iterations = 0;
  1252. while (iterations < GS_EPA_MAX_NUM_ITERATIONS)
  1253. {
  1254. // Find closest edge to origin from simplex
  1255. e = gs_gjk_epa_find_closest_edge(polytope);
  1256. p = gs_gjk_generate_support_point(ci0, ci1, e.normal);
  1257. double d = (double)gs_vec3_dot(p.minkowski_hull_vert, e.normal);
  1258. // Success, calculate results
  1259. if (d - e.distance < GS_EPA_TOLERANCE)
  1260. {
  1261. // Normal and depth information
  1262. res.normal = gs_vec3_norm(e.normal);
  1263. res.depth = d;
  1264. break;
  1265. }
  1266. else
  1267. {
  1268. // Need to think about this more. This is fucked.
  1269. // Need an "expanding" simplex, that only allows for unique points to be included.
  1270. // This is just overwriting. I need to actually insert then push back.
  1271. // gs_gjk_simplex_insert(simplex, e.index + 1, p);
  1272. // Insert into polytope array at idx + 1
  1273. for (uint32_t i = 0; i < gs_dyn_array_size(polytope); ++i)
  1274. {
  1275. gs_vec3* p = &polytope[i].minkowski_hull_vert;
  1276. gs_printf("<%.2f, %.2f>, ", p->x, p->y);
  1277. }
  1278. gs_dyn_array_push(polytope, p);
  1279. for (int32_t i = gs_dyn_array_size(polytope) - 1; i > e.index + 1; i--)
  1280. polytope[i] = polytope[i - 1];
  1281. polytope[e.index + 1] = p;
  1282. gs_println("pts after: ");
  1283. for (uint32_t i = 0; i < gs_dyn_array_size(polytope); ++i)
  1284. {
  1285. gs_vec3* p = &polytope[i].minkowski_hull_vert;
  1286. gs_printf("<%.2f, %.2f>, ", p->x, p->y);
  1287. }
  1288. }
  1289. // Increment iterations
  1290. iterations++;
  1291. }
  1292. // gs_vec3 line_vec = gs_vec3_sub(e.a.minkowski_hull_vert, e.b.minkowski_hull_vert);
  1293. // gs_vec3 projO = gs_vec3_scale(gs_vec3_scale(line_vec, 1.f / gs_vec3_len2(line_vec)), gs_vec3_dot(line_vec, gs_vec3_neg(e.b.minkowski_hull_vert)));
  1294. // float s, t;
  1295. // s = sqrt(gs_vec3_len2(projO) / gs_vec3_len2(line_vec));
  1296. // t = 1.f - s;
  1297. // int32_t next_idx = (e.index + 1) % simplex->ct;
  1298. res.hit = true;
  1299. // res.points[0] = gs_vec3_add(gs_vec3_scale(simplex->points[e.index].support_a, s), gs_vec3_scale(simplex->points[next_idx].support_a, t));
  1300. // res.points[1] = gs_vec3_add(gs_vec3_scale(simplex->points[e.index].support_b, s), gs_vec3_scale(simplex->points[next_idx].support_b, t));
  1301. return res;
  1302. }
  1303. gs_gjk_epa_edge_t gs_gjk_epa_find_closest_edge(gs_dyn_array(gs_gjk_support_point_t) polytope)
  1304. {
  1305. gs_gjk_epa_edge_t res = gs_default_val();
  1306. float min_dist = FLT_MAX;
  1307. uint32_t min_index = 0;
  1308. gs_vec3 min_normal = gs_default_val();
  1309. for (uint32_t i = 0; i < gs_dyn_array_size(polytope); ++i)
  1310. {
  1311. uint32_t j = (i + 1) % gs_dyn_array_size(polytope);
  1312. gs_gjk_support_point_t* a = &polytope[0];
  1313. gs_gjk_support_point_t* b = &polytope[1];
  1314. gs_vec3 dir = gs_vec3_sub(b->minkowski_hull_vert, a->minkowski_hull_vert);
  1315. gs_vec3 norm = gs_vec3_norm(gs_v3(dir.y, -dir.x, 0.f));
  1316. float dist = gs_vec3_dot(norm, a->minkowski_hull_vert);
  1317. // If distance is negative, then we need to correct for winding order mistakes
  1318. if (dist < 0) {
  1319. dist *= -1;
  1320. norm = gs_vec3_neg(norm);
  1321. }
  1322. // Check for min distance
  1323. if (dist < min_dist) {
  1324. min_dist = dist;
  1325. min_normal = norm;
  1326. min_index = j;
  1327. }
  1328. }
  1329. res.index = min_index;
  1330. res.normal = min_normal;
  1331. res.distance = min_dist;
  1332. return res;
  1333. }
  1334. gs_gjk_epa_edge_t gs_gjk_epa_find_closest_edge2(gs_gjk_simplex_t* simplex)
  1335. {
  1336. gs_gjk_epa_edge_t result = gs_default_val();
  1337. uint32_t next_idx = 0;
  1338. float min_dist = FLT_MAX, curr_dist = 0.f;
  1339. gs_vec3 norm, edge;
  1340. gs_vec3 norm_3d;
  1341. for (int32_t i = 0; i < simplex->ct; ++i)
  1342. {
  1343. next_idx = (i + 1) % simplex->ct;
  1344. edge = gs_vec3_sub(simplex->points[next_idx].minkowski_hull_vert, simplex->points[i].minkowski_hull_vert);
  1345. norm_3d = gs_vec3_triple_cross_product(gs_v3(edge.x, edge.y, 0),
  1346. gs_v3(simplex->points[i].minkowski_hull_vert.x, simplex->points[i].minkowski_hull_vert.y, 0.f),
  1347. gs_v3(edge.x, edge.y, 0.f));
  1348. norm.x = norm_3d.x;
  1349. norm.y = norm_3d.y;
  1350. norm = gs_vec3_norm(norm);
  1351. curr_dist = gs_vec3_dot(norm, simplex->points[i].minkowski_hull_vert);
  1352. if (curr_dist < min_dist)
  1353. {
  1354. min_dist = curr_dist;
  1355. result.a = simplex->points[i];
  1356. result.b = simplex->points[next_idx];
  1357. result.normal = norm;
  1358. result.distance = curr_dist;
  1359. result.index = i;
  1360. }
  1361. }
  1362. return result;
  1363. }
  1364. */
  1365. /*===== CCD ======*/
  1366. // Useful CCD conversions
  1367. void _gs_ccdv32gsv3(const ccd_vec3_t* _in, gs_vec3* _out)
  1368. {
  1369. // Safe check against NaNs
  1370. if (gs_is_nan(_in->v[0]) || gs_is_nan(_in->v[1]) || gs_is_nan(_in->v[2])) return;
  1371. *_out = gs_ctor(gs_vec3, (float)_in->v[0], (float)_in->v[1], (float)_in->v[2]);
  1372. }
  1373. void _gs_gsv32ccdv3(const gs_vec3* _in, ccd_vec3_t* _out)
  1374. {
  1375. ccdVec3Set(_out, CCD_REAL(_in->x), CCD_REAL(_in->y), CCD_REAL(_in->z));
  1376. }
  1377. GS_API_PRIVATE int32_t _gs_ccd_gjk_internal(
  1378. const void* c0, const gs_vqs* xform_a, gs_support_func_t f0,
  1379. const void* c1, const gs_vqs* xform_b, gs_support_func_t f1,
  1380. gs_contact_info_t* res
  1381. )
  1382. {
  1383. // Convert to appropriate gjk internals, then call ccd
  1384. ccd_t ccd = gs_default_val();
  1385. CCD_INIT(&ccd);
  1386. // set up ccd_t struct
  1387. ccd.support1 = _gs_ccd_support_func; // support function for first object
  1388. ccd.support2 = _gs_ccd_support_func; // support function for second object
  1389. ccd.max_iterations = 100; // maximal number of iterations
  1390. ccd.epa_tolerance = 0.0001; // maximal tolerance for epa to succeed
  1391. // Default transforms
  1392. gs_vqs _xa = gs_vqs_default(), _xb = gs_vqs_default();
  1393. // Collision object 1
  1394. _gs_collision_obj_handle_t h0 = gs_default_val();
  1395. h0.support = f0;
  1396. h0.obj = c0;
  1397. h0.xform = xform_a ? xform_a : &_xa;
  1398. // Collision object 2
  1399. _gs_collision_obj_handle_t h1 = gs_default_val();
  1400. h1.support = f1;
  1401. h1.obj = c1;
  1402. h1.xform = xform_b ? xform_b : &_xb;
  1403. // Call ccd, cache results into res for user
  1404. ccd_real_t depth = CCD_REAL(0.0);
  1405. ccd_vec3_t n = gs_ctor(ccd_vec3_t, 0.f, 0.f, 0.f), p = gs_ctor(ccd_vec3_t, 0.f, 0.f, 0.f);
  1406. int32_t r = ccdGJKPenetration(&h0, &h1, &ccd, &depth, &n, &p);
  1407. bool32 hit = r >= 0 && !gs_is_nan(n.v[0]) && !gs_is_nan(n.v[1]) && !gs_is_nan(n.v[2]);
  1408. if (hit && res)
  1409. {
  1410. res->hit = true;
  1411. res->depth = (float)depth;
  1412. _gs_ccdv32gsv3(&p, &res->point);
  1413. _gs_ccdv32gsv3(&n, &res->normal);
  1414. }
  1415. return r;
  1416. }
  1417. // typedef void (*ccd_support_fn)(const void *obj, const ccd_vec3_t *dir,
  1418. // ccd_vec3_t *vec);
  1419. // Internal support function for gs -> ccd
  1420. GS_API_DECL void _gs_ccd_support_func(const void* _obj, const ccd_vec3_t* _dir, ccd_vec3_t* _out)
  1421. {
  1422. const _gs_collision_obj_handle_t* obj = (const _gs_collision_obj_handle_t*)_obj;
  1423. if (obj->support)
  1424. {
  1425. // Temp copy conversion for direction vector
  1426. gs_vec3 dir = gs_default_val(), out = gs_default_val();
  1427. _gs_ccdv32gsv3((const ccd_vec3_t*)_dir, &dir);
  1428. // Call user provided support function
  1429. // Think I found it...
  1430. obj->support(obj->obj, obj->xform, &dir, &out);
  1431. // Copy over out result for ccd
  1432. _gs_gsv32ccdv3(&out, (ccd_vec3_t*)_out);
  1433. }
  1434. }
  1435. #endif // GS_PHYSICS_IMPL
  1436. #endif // GS_PHYSICS_H