gjk.cpp 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400
  1. //-----------------------------------------------------------------------------
  2. // Copyright (c) 2012 GarageGames, LLC
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to
  6. // deal in the Software without restriction, including without limitation the
  7. // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  8. // sell copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
  20. // IN THE SOFTWARE.
  21. //-----------------------------------------------------------------------------
  22. // The core algorithms in this file are inspired by public papers written
  23. // by G. van den Bergen for his interference detection library,
  24. // "SOLID 2.0"
  25. #include "core/dataChunker.h"
  26. #include "collision/collision.h"
  27. #include "scene/sceneObject.h"
  28. #include "collision/convex.h"
  29. #include "collision/gjk.h"
  30. //----------------------------------------------------------------------------
  31. static F32 rel_error = 1E-5f; // relative error in the computed distance
  32. static F32 sTolerance = 1E-3f; // Distance tolerance
  33. static F32 sEpsilon2 = 1E-20f; // Zero length vector
  34. static U32 sIteration = 15; // Stuck in a loop?
  35. S32 num_iterations = 0;
  36. S32 num_irregularities = 0;
  37. //----------------------------------------------------------------------------
  38. GjkCollisionState::GjkCollisionState()
  39. {
  40. mBits = 0;
  41. mAll_bits = 0;
  42. U32 x, y;
  43. for (x = 0; x < 16; x++)
  44. for (y = 0; y < 4; y++)
  45. mDet[x][y] = 0.0f;
  46. for (x = 0; x < 4; x++)
  47. for (y = 0; y < 4; y++)
  48. mDP[x][y] = 0.0f;
  49. mLast = 0;
  50. mLast_bit = 0;
  51. mA = mB = 0;
  52. }
  53. GjkCollisionState::~GjkCollisionState()
  54. {
  55. }
  56. //----------------------------------------------------------------------------
  57. void GjkCollisionState::swap()
  58. {
  59. Convex* t = mA; mA = mB; mB = t;
  60. CollisionStateList* l = mLista; mLista = mListb; mListb = l;
  61. mDistvec.neg();
  62. }
  63. //----------------------------------------------------------------------------
  64. void GjkCollisionState::compute_det()
  65. {
  66. // Dot new point with current set
  67. for (S32 i = 0, bit = 1; i < 4; ++i, bit <<=1)
  68. if (mBits & bit)
  69. mDP[i][mLast] = mDP[mLast][i] = mDot(mY[i], mY[mLast]);
  70. mDP[mLast][mLast] = mDot(mY[mLast], mY[mLast]);
  71. // Calulate the determinent
  72. mDet[mLast_bit][mLast] = 1;
  73. for (S32 j = 0, sj = 1; j < 4; ++j, sj <<= 1) {
  74. if (mBits & sj) {
  75. S32 s2 = sj | mLast_bit;
  76. mDet[s2][j] = mDP[mLast][mLast] - mDP[mLast][j];
  77. mDet[s2][mLast] = mDP[j][j] - mDP[j][mLast];
  78. for (S32 k = 0, sk = 1; k < j; ++k, sk <<= 1) {
  79. if (mBits & sk) {
  80. S32 s3 = sk | s2;
  81. mDet[s3][k] = mDet[s2][j] * (mDP[j][j] - mDP[j][k]) +
  82. mDet[s2][mLast] * (mDP[mLast][j] - mDP[mLast][k]);
  83. mDet[s3][j] = mDet[sk | mLast_bit][k] * (mDP[k][k] - mDP[k][j]) +
  84. mDet[sk | mLast_bit][mLast] * (mDP[mLast][k] - mDP[mLast][j]);
  85. mDet[s3][mLast] = mDet[sk | sj][k] * (mDP[k][k] - mDP[k][mLast]) +
  86. mDet[sk | sj][j] * (mDP[j][k] - mDP[j][mLast]);
  87. }
  88. }
  89. }
  90. }
  91. if (mAll_bits == 15) {
  92. mDet[15][0] = mDet[14][1] * (mDP[1][1] - mDP[1][0]) +
  93. mDet[14][2] * (mDP[2][1] - mDP[2][0]) +
  94. mDet[14][3] * (mDP[3][1] - mDP[3][0]);
  95. mDet[15][1] = mDet[13][0] * (mDP[0][0] - mDP[0][1]) +
  96. mDet[13][2] * (mDP[2][0] - mDP[2][1]) +
  97. mDet[13][3] * (mDP[3][0] - mDP[3][1]);
  98. mDet[15][2] = mDet[11][0] * (mDP[0][0] - mDP[0][2]) +
  99. mDet[11][1] * (mDP[1][0] - mDP[1][2]) +
  100. mDet[11][3] * (mDP[3][0] - mDP[3][2]);
  101. mDet[15][3] = mDet[7][0] * (mDP[0][0] - mDP[0][3]) +
  102. mDet[7][1] * (mDP[1][0] - mDP[1][3]) +
  103. mDet[7][2] * (mDP[2][0] - mDP[2][3]);
  104. }
  105. }
  106. //----------------------------------------------------------------------------
  107. inline void GjkCollisionState::compute_vector(S32 bits, VectorF& v)
  108. {
  109. F32 sum = 0;
  110. v.set(0, 0, 0);
  111. for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
  112. if (bits & bit) {
  113. sum += mDet[bits][i];
  114. v += mY[i] * mDet[bits][i];
  115. }
  116. }
  117. v *= 1 / sum;
  118. }
  119. //----------------------------------------------------------------------------
  120. inline bool GjkCollisionState::valid(S32 s)
  121. {
  122. for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
  123. if (mAll_bits & bit) {
  124. if (s & bit) {
  125. if (mDet[s][i] <= 0)
  126. return false;
  127. }
  128. else
  129. if (mDet[s | bit][i] > 0)
  130. return false;
  131. }
  132. }
  133. return true;
  134. }
  135. //----------------------------------------------------------------------------
  136. inline bool GjkCollisionState::closest(VectorF& v)
  137. {
  138. compute_det();
  139. for (S32 s = mBits; s; --s) {
  140. if ((s & mBits) == s) {
  141. if (valid(s | mLast_bit)) {
  142. mBits = s | mLast_bit;
  143. if (mBits != 15)
  144. compute_vector(mBits, v);
  145. return true;
  146. }
  147. }
  148. }
  149. if (valid(mLast_bit)) {
  150. mBits = mLast_bit;
  151. v = mY[mLast];
  152. return true;
  153. }
  154. return false;
  155. }
  156. //----------------------------------------------------------------------------
  157. inline bool GjkCollisionState::degenerate(const VectorF& w)
  158. {
  159. for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1)
  160. if ((mAll_bits & bit) && mY[i] == w)
  161. return true;
  162. return false;
  163. }
  164. //----------------------------------------------------------------------------
  165. inline void GjkCollisionState::nextBit()
  166. {
  167. mLast = 0;
  168. mLast_bit = 1;
  169. while (mBits & mLast_bit) {
  170. ++mLast;
  171. mLast_bit <<= 1;
  172. }
  173. }
  174. //----------------------------------------------------------------------------
  175. //----------------------------------------------------------------------------
  176. //----------------------------------------------------------------------------
  177. void GjkCollisionState::set(Convex* aa, Convex* bb,
  178. const MatrixF& a2w, const MatrixF& b2w)
  179. {
  180. mA = aa;
  181. mB = bb;
  182. mBits = 0;
  183. mAll_bits = 0;
  184. reset(a2w,b2w);
  185. // link
  186. mLista = CollisionStateList::alloc();
  187. mLista->mState = this;
  188. mListb = CollisionStateList::alloc();
  189. mListb->mState = this;
  190. }
  191. //----------------------------------------------------------------------------
  192. void GjkCollisionState::reset(const MatrixF& a2w, const MatrixF& b2w)
  193. {
  194. VectorF zero(0,0,0),sa,sb;
  195. a2w.mulP(mA->support(zero),&sa);
  196. b2w.mulP(mB->support(zero),&sb);
  197. mDistvec = sa - sb;
  198. mDist = mDistvec.len();
  199. }
  200. //----------------------------------------------------------------------------
  201. void GjkCollisionState::getCollisionInfo(const MatrixF& mat, Collision* info)
  202. {
  203. AssertFatal(false, "GjkCollisionState::getCollisionInfo() - There remain scaling problems here.");
  204. // This assumes that the shapes do not intersect
  205. Point3F pa,pb;
  206. if (mBits) {
  207. getClosestPoints(pa,pb);
  208. mat.mulP(pa,&info->point);
  209. mB->getTransform().mulP(pb,&pa);
  210. info->normal = info->point - pa;
  211. }
  212. else {
  213. mat.mulP(mP[mLast],&info->point);
  214. info->normal = mDistvec;
  215. }
  216. info->normal.normalize();
  217. info->object = mB->getObject();
  218. }
  219. void GjkCollisionState::getClosestPoints(Point3F& p1, Point3F& p2)
  220. {
  221. F32 sum = 0;
  222. p1.set(0, 0, 0);
  223. p2.set(0, 0, 0);
  224. for (S32 i = 0, bit = 1; i < 4; ++i, bit <<= 1) {
  225. if (mBits & bit) {
  226. sum += mDet[mBits][i];
  227. p1 += mP[i] * mDet[mBits][i];
  228. p2 += mQ[i] * mDet[mBits][i];
  229. }
  230. }
  231. F32 s = 1 / sum;
  232. p1 *= s;
  233. p2 *= s;
  234. }
  235. //----------------------------------------------------------------------------
  236. bool GjkCollisionState::intersect(const MatrixF& a2w, const MatrixF& b2w)
  237. {
  238. num_iterations = 0;
  239. MatrixF w2a,w2b;
  240. w2a = a2w;
  241. w2b = b2w;
  242. w2a.inverse();
  243. w2b.inverse();
  244. reset(a2w,b2w);
  245. mBits = 0;
  246. mAll_bits = 0;
  247. do {
  248. nextBit();
  249. VectorF va,sa;
  250. w2a.mulV(-mDistvec,&va);
  251. mP[mLast] = mA->support(va);
  252. a2w.mulP(mP[mLast],&sa);
  253. VectorF vb,sb;
  254. w2b.mulV(mDistvec,&vb);
  255. mQ[mLast] = mB->support(vb);
  256. b2w.mulP(mQ[mLast],&sb);
  257. VectorF w = sa - sb;
  258. if (mDot(mDistvec,w) > 0)
  259. return false;
  260. if (degenerate(w)) {
  261. ++num_irregularities;
  262. return false;
  263. }
  264. mY[mLast] = w;
  265. mAll_bits = mBits | mLast_bit;
  266. ++num_iterations;
  267. if (!closest(mDistvec) || num_iterations > sIteration) {
  268. ++num_irregularities;
  269. return false;
  270. }
  271. }
  272. while (mBits < 15 && mDistvec.lenSquared() > sEpsilon2);
  273. return true;
  274. }
  275. F32 GjkCollisionState::distance(const MatrixF& a2w, const MatrixF& b2w,
  276. const F32 dontCareDist, const MatrixF* _w2a, const MatrixF* _w2b)
  277. {
  278. num_iterations = 0;
  279. MatrixF w2a,w2b;
  280. if (_w2a == NULL || _w2b == NULL) {
  281. w2a = a2w;
  282. w2b = b2w;
  283. w2a.inverse();
  284. w2b.inverse();
  285. }
  286. else {
  287. w2a = *_w2a;
  288. w2b = *_w2b;
  289. }
  290. reset(a2w,b2w);
  291. mBits = 0;
  292. mAll_bits = 0;
  293. F32 mu = 0;
  294. do {
  295. nextBit();
  296. VectorF va,sa;
  297. w2a.mulV(-mDistvec,&va);
  298. mP[mLast] = mA->support(va);
  299. a2w.mulP(mP[mLast],&sa);
  300. VectorF vb,sb;
  301. w2b.mulV(mDistvec,&vb);
  302. mQ[mLast] = mB->support(vb);
  303. b2w.mulP(mQ[mLast],&sb);
  304. VectorF w = sa - sb;
  305. F32 nm = mDot(mDistvec, w) / mDist;
  306. if (nm > mu)
  307. mu = nm;
  308. if (mu > dontCareDist)
  309. return mu;
  310. if (mFabs(mDist - mu) <= mDist * rel_error)
  311. return mDist;
  312. ++num_iterations;
  313. if (degenerate(w) || num_iterations > sIteration) {
  314. ++num_irregularities;
  315. return mDist;
  316. }
  317. mY[mLast] = w;
  318. mAll_bits = mBits | mLast_bit;
  319. if (!closest(mDistvec)) {
  320. ++num_irregularities;
  321. return mDist;
  322. }
  323. mDist = mDistvec.len();
  324. }
  325. while (mBits < 15 && mDist > sTolerance) ;
  326. if (mBits == 15 && mu <= 0)
  327. mDist = 0;
  328. return mDist;
  329. }