collision_libccd.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429
  1. /*************************************************************************
  2. * *
  3. * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
  4. * All rights reserved. Email: [email protected] Web: www.q12.org *
  5. * *
  6. * This library is free software; you can redistribute it and/or *
  7. * modify it under the terms of EITHER: *
  8. * (1) The GNU Lesser General Public License as published by the Free *
  9. * Software Foundation; either version 2.1 of the License, or (at *
  10. * your option) any later version. The text of the GNU Lesser *
  11. * General Public License is included with this library in the *
  12. * file LICENSE.TXT. *
  13. * (2) The BSD-style license that is included with this library in *
  14. * the file LICENSE-BSD.TXT. *
  15. * *
  16. * This library is distributed in the hope that it will be useful, *
  17. * but WITHOUT ANY WARRANTY; without even the implied warranty of *
  18. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
  19. * LICENSE.TXT and LICENSE-BSD.TXT for more details. *
  20. * *
  21. *************************************************************************/
  22. #include <ode/collision.h>
  23. #include <ccd/ccd.h>
  24. #include <ccd/quat.h>
  25. #include "config.h"
  26. #include "odemath.h"
  27. #include "collision_libccd.h"
  28. #include "collision_std.h"
  29. struct _ccd_obj_t {
  30. ccd_vec3_t pos;
  31. ccd_quat_t rot, rot_inv;
  32. };
  33. typedef struct _ccd_obj_t ccd_obj_t;
  34. struct _ccd_box_t {
  35. ccd_obj_t o;
  36. ccd_real_t dim[3];
  37. };
  38. typedef struct _ccd_box_t ccd_box_t;
  39. struct _ccd_cap_t {
  40. ccd_obj_t o;
  41. ccd_real_t radius, height;
  42. };
  43. typedef struct _ccd_cap_t ccd_cap_t;
  44. struct _ccd_cyl_t {
  45. ccd_obj_t o;
  46. ccd_real_t radius, height;
  47. };
  48. typedef struct _ccd_cyl_t ccd_cyl_t;
  49. struct _ccd_sphere_t {
  50. ccd_obj_t o;
  51. ccd_real_t radius;
  52. };
  53. typedef struct _ccd_sphere_t ccd_sphere_t;
  54. struct _ccd_convex_t {
  55. ccd_obj_t o;
  56. dxConvex *convex;
  57. };
  58. typedef struct _ccd_convex_t ccd_convex_t;
  59. /** Transforms geom to ccd struct */
  60. static void ccdGeomToObj(const dGeomID g, ccd_obj_t *);
  61. static void ccdGeomToBox(const dGeomID g, ccd_box_t *);
  62. static void ccdGeomToCap(const dGeomID g, ccd_cap_t *);
  63. static void ccdGeomToCyl(const dGeomID g, ccd_cyl_t *);
  64. static void ccdGeomToSphere(const dGeomID g, ccd_sphere_t *);
  65. static void ccdGeomToConvex(const dGeomID g, ccd_convex_t *);
  66. /** Support functions */
  67. static void ccdSupportBox(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v);
  68. static void ccdSupportCap(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v);
  69. static void ccdSupportCyl(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v);
  70. static void ccdSupportSphere(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v);
  71. static void ccdSupportConvex(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v);
  72. /** Center function */
  73. static void ccdCenter(const void *obj, ccd_vec3_t *c);
  74. /** General collide function */
  75. static int ccdCollide(dGeomID o1, dGeomID o2, int flags,
  76. dContactGeom *contact, int skip,
  77. void *obj1, ccd_support_fn supp1, ccd_center_fn cen1,
  78. void *obj2, ccd_support_fn supp2, ccd_center_fn cen2);
  79. static void ccdGeomToObj(const dGeomID g, ccd_obj_t *o)
  80. {
  81. const dReal *ode_pos;
  82. dQuaternion ode_rot;
  83. ode_pos = dGeomGetPosition(g);
  84. dGeomGetQuaternion(g, ode_rot);
  85. ccdVec3Set(&o->pos, ode_pos[0], ode_pos[1], ode_pos[2]);
  86. ccdQuatSet(&o->rot, ode_rot[1], ode_rot[2], ode_rot[3], ode_rot[0]);
  87. ccdQuatInvert2(&o->rot_inv, &o->rot);
  88. }
  89. static void ccdGeomToBox(const dGeomID g, ccd_box_t *box)
  90. {
  91. dVector3 dim;
  92. ccdGeomToObj(g, (ccd_obj_t *)box);
  93. dGeomBoxGetLengths(g, dim);
  94. box->dim[0] = dim[0] / 2.;
  95. box->dim[1] = dim[1] / 2.;
  96. box->dim[2] = dim[2] / 2.;
  97. }
  98. static void ccdGeomToCap(const dGeomID g, ccd_cap_t *cap)
  99. {
  100. dReal r, h;
  101. ccdGeomToObj(g, (ccd_obj_t *)cap);
  102. dGeomCapsuleGetParams(g, &r, &h);
  103. cap->radius = r;
  104. cap->height = h / 2.;
  105. }
  106. static void ccdGeomToCyl(const dGeomID g, ccd_cyl_t *cyl)
  107. {
  108. dReal r, h;
  109. ccdGeomToObj(g, (ccd_obj_t *)cyl);
  110. dGeomCylinderGetParams(g, &r, &h);
  111. cyl->radius = r;
  112. cyl->height = h / 2.;
  113. }
  114. static void ccdGeomToSphere(const dGeomID g, ccd_sphere_t *s)
  115. {
  116. ccdGeomToObj(g, (ccd_obj_t *)s);
  117. s->radius = dGeomSphereGetRadius(g);
  118. }
  119. static void ccdGeomToConvex(const dGeomID g, ccd_convex_t *c)
  120. {
  121. ccdGeomToObj(g, (ccd_obj_t *)c);
  122. c->convex = (dxConvex *)g;
  123. }
  124. static void ccdSupportBox(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v)
  125. {
  126. const ccd_box_t *o = (const ccd_box_t *)obj;
  127. ccd_vec3_t dir;
  128. ccdVec3Copy(&dir, _dir);
  129. ccdQuatRotVec(&dir, &o->o.rot_inv);
  130. ccdVec3Set(v, ccdSign(ccdVec3X(&dir)) * o->dim[0],
  131. ccdSign(ccdVec3Y(&dir)) * o->dim[1],
  132. ccdSign(ccdVec3Z(&dir)) * o->dim[2]);
  133. // transform support vertex
  134. ccdQuatRotVec(v, &o->o.rot);
  135. ccdVec3Add(v, &o->o.pos);
  136. }
  137. static void ccdSupportCap(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v)
  138. {
  139. const ccd_cap_t *o = (const ccd_cap_t *)obj;
  140. ccd_vec3_t dir, pos1, pos2;
  141. ccdVec3Copy(&dir, _dir);
  142. ccdQuatRotVec(&dir, &o->o.rot_inv);
  143. ccdVec3Set(&pos1, CCD_ZERO, CCD_ZERO, o->height);
  144. ccdVec3Set(&pos2, CCD_ZERO, CCD_ZERO, -o->height);
  145. ccdVec3Copy(v, &dir);
  146. ccdVec3Scale(v, o->radius);
  147. ccdVec3Add(&pos1, v);
  148. ccdVec3Add(&pos2, v);
  149. if (ccdVec3Dot(&dir, &pos1) > ccdVec3Dot(&dir, &pos2)){
  150. ccdVec3Copy(v, &pos1);
  151. }else{
  152. ccdVec3Copy(v, &pos2);
  153. }
  154. // transform support vertex
  155. ccdQuatRotVec(v, &o->o.rot);
  156. ccdVec3Add(v, &o->o.pos);
  157. }
  158. static void ccdSupportCyl(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v)
  159. {
  160. const ccd_cyl_t *cyl = (const ccd_cyl_t *)obj;
  161. ccd_vec3_t dir;
  162. double zdist, rad;
  163. ccdVec3Copy(&dir, _dir);
  164. ccdQuatRotVec(&dir, &cyl->o.rot_inv);
  165. zdist = dir.v[0] * dir.v[0] + dir.v[1] * dir.v[1];
  166. zdist = sqrt(zdist);
  167. if (ccdIsZero(zdist)){
  168. ccdVec3Set(v, 0., 0., ccdSign(ccdVec3Z(&dir)) * cyl->height);
  169. }else{
  170. rad = cyl->radius / zdist;
  171. ccdVec3Set(v, rad * ccdVec3X(&dir),
  172. rad * ccdVec3Y(&dir),
  173. ccdSign(ccdVec3Z(&dir)) * cyl->height);
  174. }
  175. // transform support vertex
  176. ccdQuatRotVec(v, &cyl->o.rot);
  177. ccdVec3Add(v, &cyl->o.pos);
  178. }
  179. static void ccdSupportSphere(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v)
  180. {
  181. const ccd_sphere_t *s = (const ccd_sphere_t *)obj;
  182. ccd_vec3_t dir;
  183. ccdVec3Copy(&dir, _dir);
  184. ccdQuatRotVec(&dir, &s->o.rot_inv);
  185. ccdVec3Copy(v, &dir);
  186. ccdVec3Scale(v, s->radius);
  187. ccdVec3Scale(v, CCD_ONE / CCD_SQRT(ccdVec3Len2(&dir)));
  188. // transform support vertex
  189. ccdQuatRotVec(v, &s->o.rot);
  190. ccdVec3Add(v, &s->o.pos);
  191. }
  192. static void ccdSupportConvex(const void *obj, const ccd_vec3_t *_dir, ccd_vec3_t *v)
  193. {
  194. const ccd_convex_t *c = (const ccd_convex_t *)obj;
  195. ccd_vec3_t dir, p;
  196. ccd_real_t maxdot, dot;
  197. size_t i;
  198. dReal *curp;
  199. ccdVec3Copy(&dir, _dir);
  200. ccdQuatRotVec(&dir, &c->o.rot_inv);
  201. maxdot = -CCD_REAL_MAX;
  202. curp = c->convex->points;
  203. for (i = 0; i < c->convex->pointcount; i++, curp += 3){
  204. ccdVec3Set(&p, curp[0], curp[1], curp[2]);
  205. dot = ccdVec3Dot(&dir, &p);
  206. if (dot > maxdot){
  207. ccdVec3Copy(v, &p);
  208. maxdot = dot;
  209. }
  210. }
  211. // transform support vertex
  212. ccdQuatRotVec(v, &c->o.rot);
  213. ccdVec3Add(v, &c->o.pos);
  214. }
  215. static void ccdCenter(const void *obj, ccd_vec3_t *c)
  216. {
  217. const ccd_obj_t *o = (const ccd_obj_t *)obj;
  218. ccdVec3Copy(c, &o->pos);
  219. }
  220. static int ccdCollide(
  221. dGeomID o1, dGeomID o2, int flags, dContactGeom *contact, int skip,
  222. void *obj1, ccd_support_fn supp1, ccd_center_fn cen1,
  223. void *obj2, ccd_support_fn supp2, ccd_center_fn cen2)
  224. {
  225. ccd_t ccd;
  226. int res;
  227. ccd_real_t depth;
  228. ccd_vec3_t dir, pos;
  229. int max_contacts = (flags & 0xffff);
  230. if (max_contacts < 1)
  231. return 0;
  232. CCD_INIT(&ccd);
  233. ccd.support1 = supp1;
  234. ccd.support2 = supp2;
  235. ccd.center1 = cen1;
  236. ccd.center2 = cen2;
  237. ccd.max_iterations = 500;
  238. ccd.mpr_tolerance = 1E-6;
  239. if (flags & CONTACTS_UNIMPORTANT){
  240. if (ccdMPRIntersect(obj1, obj2, &ccd)){
  241. return 1;
  242. }else{
  243. return 0;
  244. }
  245. }
  246. res = ccdMPRPenetration(obj1, obj2, &ccd, &depth, &dir, &pos);
  247. if (res == 0){
  248. contact->g1 = o1;
  249. contact->g2 = o2;
  250. contact->side1 = contact->side2 = -1;
  251. contact->depth = depth;
  252. contact->pos[0] = ccdVec3X(&pos);
  253. contact->pos[1] = ccdVec3Y(&pos);
  254. contact->pos[2] = ccdVec3Z(&pos);
  255. ccdVec3Scale(&dir, -1.);
  256. contact->normal[0] = ccdVec3X(&dir);
  257. contact->normal[1] = ccdVec3Y(&dir);
  258. contact->normal[2] = ccdVec3Z(&dir);
  259. return 1;
  260. }
  261. return 0;
  262. }
  263. int dCollideCylinderCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  264. {
  265. ccd_cyl_t cyl1, cyl2;
  266. ccdGeomToCyl(o1, &cyl1);
  267. ccdGeomToCyl(o2, &cyl2);
  268. return ccdCollide(o1, o2, flags, contact, skip,
  269. &cyl1, ccdSupportCyl, ccdCenter,
  270. &cyl2, ccdSupportCyl, ccdCenter);
  271. }
  272. int dCollideBoxCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  273. {
  274. ccd_cyl_t cyl;
  275. ccd_box_t box;
  276. ccdGeomToBox(o1, &box);
  277. ccdGeomToCyl(o2, &cyl);
  278. return ccdCollide(o1, o2, flags, contact, skip,
  279. &box, ccdSupportBox, ccdCenter,
  280. &cyl, ccdSupportCyl, ccdCenter);
  281. }
  282. int dCollideCapsuleCylinder(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  283. {
  284. ccd_cap_t cap;
  285. ccd_cyl_t cyl;
  286. ccdGeomToCap(o1, &cap);
  287. ccdGeomToCyl(o2, &cyl);
  288. return ccdCollide(o1, o2, flags, contact, skip,
  289. &cap, ccdSupportCap, ccdCenter,
  290. &cyl, ccdSupportCyl, ccdCenter);
  291. }
  292. int dCollideConvexBoxCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  293. {
  294. ccd_box_t box;
  295. ccd_convex_t conv;
  296. ccdGeomToConvex(o1, &conv);
  297. ccdGeomToBox(o2, &box);
  298. return ccdCollide(o1, o2, flags, contact, skip,
  299. &conv, ccdSupportConvex, ccdCenter,
  300. &box, ccdSupportBox, ccdCenter);
  301. }
  302. int dCollideConvexCapsuleCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  303. {
  304. ccd_cap_t cap;
  305. ccd_convex_t conv;
  306. ccdGeomToConvex(o1, &conv);
  307. ccdGeomToCap(o2, &cap);
  308. return ccdCollide(o1, o2, flags, contact, skip,
  309. &conv, ccdSupportConvex, ccdCenter,
  310. &cap, ccdSupportCap, ccdCenter);
  311. }
  312. int dCollideConvexSphereCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  313. {
  314. ccd_sphere_t sphere;
  315. ccd_convex_t conv;
  316. ccdGeomToConvex(o1, &conv);
  317. ccdGeomToSphere(o2, &sphere);
  318. return ccdCollide(o1, o2, flags, contact, skip,
  319. &conv, ccdSupportConvex, ccdCenter,
  320. &sphere, ccdSupportSphere, ccdCenter);
  321. }
  322. int dCollideConvexCylinderCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  323. {
  324. ccd_cyl_t cyl;
  325. ccd_convex_t conv;
  326. ccdGeomToConvex(o1, &conv);
  327. ccdGeomToCyl(o2, &cyl);
  328. return ccdCollide(o1, o2, flags, contact, skip,
  329. &conv, ccdSupportConvex, ccdCenter,
  330. &cyl, ccdSupportCyl, ccdCenter);
  331. }
  332. int dCollideConvexConvexCCD(dxGeom *o1, dxGeom *o2, int flags, dContactGeom *contact, int skip)
  333. {
  334. ccd_convex_t c1, c2;
  335. ccdGeomToConvex(o1, &c1);
  336. ccdGeomToConvex(o2, &c2);
  337. return ccdCollide(o1, o2, flags, contact, skip,
  338. &c1, ccdSupportConvex, ccdCenter,
  339. &c2, ccdSupportConvex, ccdCenter);
  340. }