[1963] | 1 | /* |
---|
| 2 | Bullet Continuous Collision Detection and Physics Library |
---|
| 3 | Copyright (c) 2003-2006 Erwin Coumans http://continuousphysics.com/Bullet/ |
---|
| 4 | |
---|
| 5 | This software is provided 'as-is', without any express or implied warranty. |
---|
| 6 | In no event will the authors be held liable for any damages arising from the |
---|
| 7 | use of this software. |
---|
| 8 | Permission is granted to anyone to use this software for any purpose, |
---|
| 9 | including commercial applications, and to alter it and redistribute it |
---|
| 10 | freely, |
---|
| 11 | subject to the following restrictions: |
---|
| 12 | |
---|
| 13 | 1. The origin of this software must not be misrepresented; you must not |
---|
| 14 | claim that you wrote the original software. If you use this software in a |
---|
| 15 | product, an acknowledgment in the product documentation would be appreciated |
---|
| 16 | but is not required. |
---|
| 17 | 2. Altered source versions must be plainly marked as such, and must not be |
---|
| 18 | misrepresented as being the original software. |
---|
| 19 | 3. This notice may not be removed or altered from any source distribution. |
---|
| 20 | */ |
---|
| 21 | |
---|
| 22 | /* |
---|
| 23 | GJK-EPA collision solver by Nathanael Presson |
---|
| 24 | Nov.2006 |
---|
| 25 | */ |
---|
| 26 | |
---|
| 27 | #include "btGjkEpa.h" |
---|
| 28 | #include <string.h> //for memset |
---|
| 29 | #include "LinearMath/btStackAlloc.h" |
---|
| 30 | |
---|
| 31 | #if defined(DEBUG) || defined (_DEBUG) |
---|
| 32 | #include <stdio.h> //for debug printf |
---|
| 33 | #ifdef __SPU__ |
---|
| 34 | #include <spu_printf.h> |
---|
| 35 | #define printf spu_printf |
---|
| 36 | #endif //__SPU__ |
---|
| 37 | #endif |
---|
| 38 | |
---|
| 39 | namespace gjkepa_impl |
---|
| 40 | { |
---|
| 41 | |
---|
| 42 | // |
---|
| 43 | // Port. typedefs |
---|
| 44 | // |
---|
| 45 | |
---|
| 46 | typedef btScalar F; |
---|
| 47 | typedef bool Z; |
---|
| 48 | typedef int I; |
---|
| 49 | typedef unsigned int U; |
---|
| 50 | typedef unsigned char U1; |
---|
| 51 | typedef unsigned short U2; |
---|
| 52 | |
---|
| 53 | typedef btVector3 Vector3; |
---|
| 54 | typedef btMatrix3x3 Rotation; |
---|
| 55 | |
---|
| 56 | // |
---|
| 57 | // Config |
---|
| 58 | // |
---|
| 59 | |
---|
| 60 | #if 0 |
---|
| 61 | #define BTLOCALSUPPORT localGetSupportingVertexWithoutMargin |
---|
| 62 | #else |
---|
| 63 | #define BTLOCALSUPPORT localGetSupportingVertex |
---|
| 64 | #endif |
---|
| 65 | |
---|
| 66 | // |
---|
| 67 | // Const |
---|
| 68 | // |
---|
| 69 | |
---|
| 70 | |
---|
| 71 | #define cstInf SIMD_INFINITY |
---|
| 72 | #define cstPi SIMD_PI |
---|
| 73 | #define cst2Pi SIMD_2_PI |
---|
| 74 | #define GJK_maxiterations (128) |
---|
| 75 | #define GJK_hashsize (1<<6) |
---|
| 76 | #define GJK_hashmask (GJK_hashsize-1) |
---|
| 77 | #define GJK_insimplex_eps F(0.0001) |
---|
| 78 | #define GJK_sqinsimplex_eps (GJK_insimplex_eps*GJK_insimplex_eps) |
---|
| 79 | #define EPA_maxiterations 256 |
---|
| 80 | #define EPA_inface_eps F(0.01) |
---|
| 81 | #define EPA_accuracy F(0.001) |
---|
| 82 | |
---|
| 83 | // |
---|
| 84 | // Utils |
---|
| 85 | // |
---|
| 86 | |
---|
| 87 | static inline F Abs(F v) { return(v<0?-v:v); } |
---|
| 88 | static inline F Sign(F v) { return(F(v<0?-1:1)); } |
---|
| 89 | template <typename T> static inline void Swap(T& a,T& b) { T |
---|
| 90 | t(a);a=b;b=t; } |
---|
| 91 | template <typename T> static inline T Min(const T& a,const T& b) { |
---|
| 92 | return(a<b?a:b); } |
---|
| 93 | template <typename T> static inline T Max(const T& a,const T& b) { |
---|
| 94 | return(a>b?a:b); } |
---|
| 95 | static inline void ClearMemory(void* p,U sz) { memset(p,0,(size_t)sz); |
---|
| 96 | } |
---|
| 97 | #if 0 |
---|
| 98 | template <typename T> static inline void Raise(const T& object) { |
---|
| 99 | throw(object); } |
---|
| 100 | #else |
---|
| 101 | template <typename T> static inline void Raise(const T&) {} |
---|
| 102 | #endif |
---|
| 103 | |
---|
| 104 | |
---|
| 105 | |
---|
| 106 | // |
---|
| 107 | // GJK |
---|
| 108 | // |
---|
| 109 | struct GJK |
---|
| 110 | { |
---|
| 111 | struct Mkv |
---|
| 112 | { |
---|
| 113 | Vector3 w; /* Minkowski vertice */ |
---|
| 114 | Vector3 r; /* Ray */ |
---|
| 115 | }; |
---|
| 116 | struct He |
---|
| 117 | { |
---|
| 118 | Vector3 v; |
---|
| 119 | He* n; |
---|
| 120 | }; |
---|
| 121 | btStackAlloc* sa; |
---|
| 122 | btBlock* sablock; |
---|
| 123 | He* table[GJK_hashsize]; |
---|
| 124 | Rotation wrotations[2]; |
---|
| 125 | Vector3 positions[2]; |
---|
| 126 | const btConvexShape* shapes[2]; |
---|
| 127 | Mkv simplex[5]; |
---|
| 128 | Vector3 ray; |
---|
| 129 | U order; |
---|
| 130 | U iterations; |
---|
| 131 | F margin; |
---|
| 132 | Z failed; |
---|
| 133 | // |
---|
| 134 | GJK(btStackAlloc* psa, |
---|
| 135 | const Rotation& wrot0,const Vector3& pos0,const btConvexShape* shape0, |
---|
| 136 | const Rotation& wrot1,const Vector3& pos1,const btConvexShape* shape1, |
---|
| 137 | F pmargin=0) |
---|
| 138 | { |
---|
| 139 | wrotations[0]=wrot0;positions[0]=pos0;shapes[0]=shape0; |
---|
| 140 | wrotations[1]=wrot1;positions[1]=pos1;shapes[1]=shape1; |
---|
| 141 | sa =psa; |
---|
| 142 | sablock =sa->beginBlock(); |
---|
| 143 | margin =pmargin; |
---|
| 144 | failed =false; |
---|
| 145 | } |
---|
| 146 | // |
---|
| 147 | ~GJK() |
---|
| 148 | { |
---|
| 149 | sa->endBlock(sablock); |
---|
| 150 | } |
---|
| 151 | // vdh : very dumm hash |
---|
| 152 | static inline U Hash(const Vector3& v) |
---|
| 153 | { |
---|
| 154 | //this doesn't compile under GCC 3.3.5, so add the ()... |
---|
| 155 | //const U h(U(v[0]*15461)^U(v[1]*83003)^U(v[2]*15473)); |
---|
| 156 | //return(((*((const U*)&h))*169639)&GJK_hashmask); |
---|
| 157 | const U h((U)(v[0]*15461)^(U)(v[1]*83003)^(U)(v[2]*15473)); |
---|
| 158 | return(((*((const U*)&h))*169639)&GJK_hashmask); |
---|
| 159 | } |
---|
| 160 | // |
---|
| 161 | inline Vector3 LocalSupport(const Vector3& d,U i) const |
---|
| 162 | { |
---|
| 163 | return(wrotations[i]*shapes[i]->BTLOCALSUPPORT(d*wrotations[i])+positions[i]); |
---|
| 164 | } |
---|
| 165 | // |
---|
| 166 | inline void Support(const Vector3& d,Mkv& v) const |
---|
| 167 | { |
---|
| 168 | v.r = d; |
---|
| 169 | v.w = LocalSupport(d,0)-LocalSupport(-d,1)+d*margin; |
---|
| 170 | } |
---|
| 171 | #define SPX(_i_) simplex[_i_] |
---|
| 172 | #define SPXW(_i_) simplex[_i_].w |
---|
| 173 | // |
---|
| 174 | inline Z FetchSupport() |
---|
| 175 | { |
---|
| 176 | const U h(Hash(ray)); |
---|
| 177 | He* e = (He*)(table[h]); |
---|
| 178 | while(e) { if(e->v==ray) { --order;return(false); } else e=e->n; } |
---|
| 179 | e=(He*)sa->allocate(sizeof(He));e->v=ray;e->n=table[h];table[h]=e; |
---|
| 180 | Support(ray,simplex[++order]); |
---|
| 181 | return(ray.dot(SPXW(order))>0); |
---|
| 182 | } |
---|
| 183 | // |
---|
| 184 | inline Z SolveSimplex2(const Vector3& ao,const Vector3& ab) |
---|
| 185 | { |
---|
| 186 | if(ab.dot(ao)>=0) |
---|
| 187 | { |
---|
| 188 | const Vector3 cabo(cross(ab,ao)); |
---|
| 189 | if(cabo.length2()>GJK_sqinsimplex_eps) |
---|
| 190 | { ray=cross(cabo,ab); } |
---|
| 191 | else |
---|
| 192 | { return(true); } |
---|
| 193 | } |
---|
| 194 | else |
---|
| 195 | { order=0;SPX(0)=SPX(1);ray=ao; } |
---|
| 196 | return(false); |
---|
| 197 | } |
---|
| 198 | // |
---|
| 199 | inline Z SolveSimplex3(const Vector3& ao,const Vector3& ab,const Vector3& |
---|
| 200 | ac) |
---|
| 201 | { |
---|
| 202 | return(SolveSimplex3a(ao,ab,ac,cross(ab,ac))); |
---|
| 203 | } |
---|
| 204 | // |
---|
| 205 | inline Z SolveSimplex3a(const Vector3& ao,const Vector3& ab,const Vector3& |
---|
| 206 | ac,const Vector3& cabc) |
---|
| 207 | { |
---|
| 208 | if((cross(cabc,ab)).dot(ao)<-GJK_insimplex_eps) |
---|
| 209 | { order=1;SPX(0)=SPX(1);SPX(1)=SPX(2);return(SolveSimplex2(ao,ab)); } |
---|
| 210 | else if((cross(cabc,ac)).dot(ao)>+GJK_insimplex_eps) |
---|
| 211 | { order=1;SPX(1)=SPX(2);return(SolveSimplex2(ao,ac)); } |
---|
| 212 | else |
---|
| 213 | { |
---|
| 214 | const F d(cabc.dot(ao)); |
---|
| 215 | if(Abs(d)>GJK_insimplex_eps) |
---|
| 216 | { |
---|
| 217 | if(d>0) |
---|
| 218 | { ray=cabc; } |
---|
| 219 | else |
---|
| 220 | { ray=-cabc;Swap(SPX(0),SPX(1)); } |
---|
| 221 | return(false); |
---|
| 222 | } else return(true); |
---|
| 223 | } |
---|
| 224 | } |
---|
| 225 | // |
---|
| 226 | inline Z SolveSimplex4(const Vector3& ao,const Vector3& ab,const Vector3& |
---|
| 227 | ac,const Vector3& ad) |
---|
| 228 | { |
---|
| 229 | Vector3 crs; |
---|
| 230 | if((crs=cross(ab,ac)).dot(ao)>GJK_insimplex_eps) |
---|
| 231 | { |
---|
| 232 | order=2;SPX(0)=SPX(1);SPX(1)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ab,ac,crs)); |
---|
| 233 | } |
---|
| 234 | else if((crs=cross(ac,ad)).dot(ao)>GJK_insimplex_eps) |
---|
| 235 | { order=2;SPX(2)=SPX(3);return(SolveSimplex3a(ao,ac,ad,crs)); } |
---|
| 236 | else if((crs=cross(ad,ab)).dot(ao)>GJK_insimplex_eps) |
---|
| 237 | { |
---|
| 238 | order=2;SPX(1)=SPX(0);SPX(0)=SPX(2);SPX(2)=SPX(3);return(SolveSimplex3a(ao,ad,ab,crs)); |
---|
| 239 | } |
---|
| 240 | else return(true); |
---|
| 241 | } |
---|
| 242 | // |
---|
| 243 | inline Z SearchOrigin(const Vector3& initray=Vector3(1,0,0)) |
---|
| 244 | { |
---|
| 245 | iterations = 0; |
---|
| 246 | order = (U)-1; |
---|
| 247 | failed = false; |
---|
| 248 | ray = initray.normalized(); |
---|
| 249 | ClearMemory(table,sizeof(void*)*GJK_hashsize); |
---|
| 250 | FetchSupport(); |
---|
| 251 | ray = -SPXW(0); |
---|
| 252 | for(;iterations<GJK_maxiterations;++iterations) |
---|
| 253 | { |
---|
| 254 | const F rl(ray.length()); |
---|
| 255 | ray/=rl>0?rl:1; |
---|
| 256 | if(FetchSupport()) |
---|
| 257 | { |
---|
| 258 | Z found(false); |
---|
| 259 | switch(order) |
---|
| 260 | { |
---|
| 261 | case 1: found=SolveSimplex2(-SPXW(1),SPXW(0)-SPXW(1));break; |
---|
| 262 | case 2: found=SolveSimplex3(-SPXW(2),SPXW(1)-SPXW(2),SPXW(0)-SPXW(2));break; |
---|
| 263 | case 3: found=SolveSimplex4(-SPXW(3),SPXW(2)-SPXW(3),SPXW(1)-SPXW(3),SPXW(0)-SPXW(3));break; |
---|
| 264 | } |
---|
| 265 | if(found) return(true); |
---|
| 266 | } else return(false); |
---|
| 267 | } |
---|
| 268 | failed=true; |
---|
| 269 | return(false); |
---|
| 270 | } |
---|
| 271 | // |
---|
| 272 | inline Z EncloseOrigin() |
---|
| 273 | { |
---|
| 274 | switch(order) |
---|
| 275 | { |
---|
| 276 | /* Point */ |
---|
| 277 | case 0: break; |
---|
| 278 | /* Line */ |
---|
| 279 | case 1: |
---|
| 280 | { |
---|
| 281 | const Vector3 ab(SPXW(1)-SPXW(0)); |
---|
| 282 | const Vector3 b[]={ cross(ab,Vector3(1,0,0)), |
---|
| 283 | cross(ab,Vector3(0,1,0)), |
---|
| 284 | cross(ab,Vector3(0,0,1))}; |
---|
| 285 | const F m[]={b[0].length2(),b[1].length2(),b[2].length2()}; |
---|
| 286 | const Rotation r(btQuaternion(ab.normalized(),cst2Pi/3)); |
---|
| 287 | Vector3 w(b[m[0]>m[1]?m[0]>m[2]?0:2:m[1]>m[2]?1:2]); |
---|
| 288 | Support(w.normalized(),simplex[4]);w=r*w; |
---|
| 289 | Support(w.normalized(),simplex[2]);w=r*w; |
---|
| 290 | Support(w.normalized(),simplex[3]);w=r*w; |
---|
| 291 | order=4; |
---|
| 292 | return(true); |
---|
| 293 | } |
---|
| 294 | break; |
---|
| 295 | /* Triangle */ |
---|
| 296 | case 2: |
---|
| 297 | { |
---|
| 298 | const |
---|
| 299 | Vector3 n(cross((SPXW(1)-SPXW(0)),(SPXW(2)-SPXW(0))).normalized()); |
---|
| 300 | Support( n,simplex[3]); |
---|
| 301 | Support(-n,simplex[4]); |
---|
| 302 | order=4; |
---|
| 303 | return(true); |
---|
| 304 | } |
---|
| 305 | break; |
---|
| 306 | /* Tetrahedron */ |
---|
| 307 | case 3: return(true); |
---|
| 308 | /* Hexahedron */ |
---|
| 309 | case 4: return(true); |
---|
| 310 | } |
---|
| 311 | return(false); |
---|
| 312 | } |
---|
| 313 | #undef SPX |
---|
| 314 | #undef SPXW |
---|
| 315 | }; |
---|
| 316 | |
---|
| 317 | // |
---|
| 318 | // EPA |
---|
| 319 | // |
---|
| 320 | struct EPA |
---|
| 321 | { |
---|
| 322 | // |
---|
| 323 | struct Face |
---|
| 324 | { |
---|
| 325 | const GJK::Mkv* v[3]; |
---|
| 326 | Face* f[3]; |
---|
| 327 | U e[3]; |
---|
| 328 | Vector3 n; |
---|
| 329 | F d; |
---|
| 330 | U mark; |
---|
| 331 | Face* prev; |
---|
| 332 | Face* next; |
---|
| 333 | Face() {} |
---|
| 334 | }; |
---|
| 335 | // |
---|
| 336 | GJK* gjk; |
---|
| 337 | btStackAlloc* sa; |
---|
| 338 | Face* root; |
---|
| 339 | U nfaces; |
---|
| 340 | U iterations; |
---|
| 341 | Vector3 features[2][3]; |
---|
| 342 | Vector3 nearest[2]; |
---|
| 343 | Vector3 normal; |
---|
| 344 | F depth; |
---|
| 345 | Z failed; |
---|
| 346 | // |
---|
| 347 | EPA(GJK* pgjk) |
---|
| 348 | { |
---|
| 349 | gjk = pgjk; |
---|
| 350 | sa = pgjk->sa; |
---|
| 351 | } |
---|
| 352 | // |
---|
| 353 | ~EPA() |
---|
| 354 | { |
---|
| 355 | } |
---|
| 356 | // |
---|
| 357 | inline Vector3 GetCoordinates(const Face* face) const |
---|
| 358 | { |
---|
| 359 | const Vector3 o(face->n*-face->d); |
---|
| 360 | const F a[]={ cross(face->v[0]->w-o,face->v[1]->w-o).length(), |
---|
| 361 | cross(face->v[1]->w-o,face->v[2]->w-o).length(), |
---|
| 362 | cross(face->v[2]->w-o,face->v[0]->w-o).length()}; |
---|
| 363 | const F sm(a[0]+a[1]+a[2]); |
---|
| 364 | return(Vector3(a[1],a[2],a[0])/(sm>0?sm:1)); |
---|
| 365 | } |
---|
| 366 | // |
---|
| 367 | inline Face* FindBest() const |
---|
| 368 | { |
---|
| 369 | Face* bf = 0; |
---|
| 370 | if(root) |
---|
| 371 | { |
---|
| 372 | Face* cf = root; |
---|
| 373 | F bd(cstInf); |
---|
| 374 | do { |
---|
| 375 | if(cf->d<bd) { bd=cf->d;bf=cf; } |
---|
| 376 | } while(0!=(cf=cf->next)); |
---|
| 377 | } |
---|
| 378 | return(bf); |
---|
| 379 | } |
---|
| 380 | // |
---|
| 381 | inline Z Set(Face* f,const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* |
---|
| 382 | c) const |
---|
| 383 | { |
---|
| 384 | const Vector3 nrm(cross(b->w-a->w,c->w-a->w)); |
---|
| 385 | const F len(nrm.length()); |
---|
| 386 | const Z valid( (cross(a->w,b->w).dot(nrm)>=-EPA_inface_eps)&& |
---|
| 387 | (cross(b->w,c->w).dot(nrm)>=-EPA_inface_eps)&& |
---|
| 388 | (cross(c->w,a->w).dot(nrm)>=-EPA_inface_eps)); |
---|
| 389 | f->v[0] = a; |
---|
| 390 | f->v[1] = b; |
---|
| 391 | f->v[2] = c; |
---|
| 392 | f->mark = 0; |
---|
| 393 | f->n = nrm/(len>0?len:cstInf); |
---|
| 394 | f->d = Max<F>(0,-f->n.dot(a->w)); |
---|
| 395 | return(valid); |
---|
| 396 | } |
---|
| 397 | // |
---|
| 398 | inline Face* NewFace(const GJK::Mkv* a,const GJK::Mkv* b,const GJK::Mkv* c) |
---|
| 399 | { |
---|
| 400 | Face* pf = (Face*)sa->allocate(sizeof(Face)); |
---|
| 401 | if(Set(pf,a,b,c)) |
---|
| 402 | { |
---|
| 403 | if(root) root->prev=pf; |
---|
| 404 | pf->prev=0; |
---|
| 405 | pf->next=root; |
---|
| 406 | root =pf; |
---|
| 407 | ++nfaces; |
---|
| 408 | } |
---|
| 409 | else |
---|
| 410 | { |
---|
| 411 | pf->prev=pf->next=0; |
---|
| 412 | } |
---|
| 413 | return(pf); |
---|
| 414 | } |
---|
| 415 | // |
---|
| 416 | inline void Detach(Face* face) |
---|
| 417 | { |
---|
| 418 | if(face->prev||face->next) |
---|
| 419 | { |
---|
| 420 | --nfaces; |
---|
| 421 | if(face==root) |
---|
| 422 | { root=face->next;root->prev=0; } |
---|
| 423 | else |
---|
| 424 | { |
---|
| 425 | if(face->next==0) |
---|
| 426 | { face->prev->next=0; } |
---|
| 427 | else |
---|
| 428 | { face->prev->next=face->next;face->next->prev=face->prev; } |
---|
| 429 | } |
---|
| 430 | face->prev=face->next=0; |
---|
| 431 | } |
---|
| 432 | } |
---|
| 433 | // |
---|
| 434 | inline void Link(Face* f0,U e0,Face* f1,U e1) const |
---|
| 435 | { |
---|
| 436 | f0->f[e0]=f1;f1->e[e1]=e0; |
---|
| 437 | f1->f[e1]=f0;f0->e[e0]=e1; |
---|
| 438 | } |
---|
| 439 | // |
---|
| 440 | GJK::Mkv* Support(const Vector3& w) const |
---|
| 441 | { |
---|
| 442 | GJK::Mkv* v =(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv)); |
---|
| 443 | gjk->Support(w,*v); |
---|
| 444 | return(v); |
---|
| 445 | } |
---|
| 446 | // |
---|
| 447 | U BuildHorizon(U markid,const GJK::Mkv* w,Face& f,U e,Face*& cf,Face*& |
---|
| 448 | ff) |
---|
| 449 | { |
---|
| 450 | static const U mod3[]={0,1,2,0,1}; |
---|
| 451 | U ne(0); |
---|
| 452 | if(f.mark!=markid) |
---|
| 453 | { |
---|
| 454 | const U e1(mod3[e+1]); |
---|
| 455 | if((f.n.dot(w->w)+f.d)>0) |
---|
| 456 | { |
---|
| 457 | Face* nf = NewFace(f.v[e1],f.v[e],w); |
---|
| 458 | Link(nf,0,&f,e); |
---|
| 459 | if(cf) Link(cf,1,nf,2); else ff=nf; |
---|
| 460 | cf=nf;ne=1; |
---|
| 461 | } |
---|
| 462 | else |
---|
| 463 | { |
---|
| 464 | const U e2(mod3[e+2]); |
---|
| 465 | Detach(&f); |
---|
| 466 | f.mark = markid; |
---|
| 467 | ne += BuildHorizon(markid,w,*f.f[e1],f.e[e1],cf,ff); |
---|
| 468 | ne += BuildHorizon(markid,w,*f.f[e2],f.e[e2],cf,ff); |
---|
| 469 | } |
---|
| 470 | } |
---|
| 471 | return(ne); |
---|
| 472 | } |
---|
| 473 | // |
---|
| 474 | inline F EvaluatePD(F accuracy=EPA_accuracy) |
---|
| 475 | { |
---|
| 476 | btBlock* sablock = sa->beginBlock(); |
---|
| 477 | Face* bestface = 0; |
---|
| 478 | U markid(1); |
---|
| 479 | depth = -cstInf; |
---|
| 480 | normal = Vector3(0,0,0); |
---|
| 481 | root = 0; |
---|
| 482 | nfaces = 0; |
---|
| 483 | iterations = 0; |
---|
| 484 | failed = false; |
---|
| 485 | /* Prepare hull */ |
---|
| 486 | if(gjk->EncloseOrigin()) |
---|
| 487 | { |
---|
| 488 | const U* pfidx = 0; |
---|
| 489 | U nfidx= 0; |
---|
| 490 | const U* peidx = 0; |
---|
| 491 | U neidx = 0; |
---|
| 492 | GJK::Mkv* basemkv[5]; |
---|
| 493 | Face* basefaces[6]; |
---|
| 494 | switch(gjk->order) |
---|
| 495 | { |
---|
| 496 | /* Tetrahedron */ |
---|
| 497 | case 3: { |
---|
| 498 | static const U fidx[4][3]={{2,1,0},{3,0,1},{3,1,2},{3,2,0}}; |
---|
| 499 | static const |
---|
| 500 | U eidx[6][4]={{0,0,2,1},{0,1,1,1},{0,2,3,1},{1,0,3,2},{2,0,1,2},{3,0,2,2}}; |
---|
| 501 | pfidx=(const U*)fidx;nfidx=4;peidx=(const U*)eidx;neidx=6; |
---|
| 502 | } break; |
---|
| 503 | /* Hexahedron */ |
---|
| 504 | case 4: { |
---|
| 505 | static const |
---|
| 506 | U fidx[6][3]={{2,0,4},{4,1,2},{1,4,0},{0,3,1},{0,2,3},{1,3,2}}; |
---|
| 507 | static const |
---|
| 508 | U eidx[9][4]={{0,0,4,0},{0,1,2,1},{0,2,1,2},{1,1,5,2},{1,0,2,0},{2,2,3,2},{3,1,5,0},{3,0,4,2},{5,1,4,1}}; |
---|
| 509 | pfidx=(const U*)fidx;nfidx=6;peidx=(const U*)eidx;neidx=9; |
---|
| 510 | } break; |
---|
| 511 | } |
---|
| 512 | U i; |
---|
| 513 | |
---|
| 514 | for( i=0;i<=gjk->order;++i) { |
---|
| 515 | basemkv[i]=(GJK::Mkv*)sa->allocate(sizeof(GJK::Mkv));*basemkv[i]=gjk->simplex[i]; |
---|
| 516 | } |
---|
| 517 | for( i=0;i<nfidx;++i,pfidx+=3) { |
---|
| 518 | basefaces[i]=NewFace(basemkv[pfidx[0]],basemkv[pfidx[1]],basemkv[pfidx[2]]); |
---|
| 519 | } |
---|
| 520 | for( i=0;i<neidx;++i,peidx+=4) { |
---|
| 521 | Link(basefaces[peidx[0]],peidx[1],basefaces[peidx[2]],peidx[3]); } |
---|
| 522 | } |
---|
| 523 | if(0==nfaces) |
---|
| 524 | { |
---|
| 525 | sa->endBlock(sablock); |
---|
| 526 | return(depth); |
---|
| 527 | } |
---|
| 528 | /* Expand hull */ |
---|
| 529 | for(;iterations<EPA_maxiterations;++iterations) |
---|
| 530 | { |
---|
| 531 | Face* bf = FindBest(); |
---|
| 532 | if(bf) |
---|
| 533 | { |
---|
| 534 | GJK::Mkv* w = Support(-bf->n); |
---|
| 535 | const F d(bf->n.dot(w->w)+bf->d); |
---|
| 536 | bestface = bf; |
---|
| 537 | if(d<-accuracy) |
---|
| 538 | { |
---|
| 539 | Face* cf =0; |
---|
| 540 | Face* ff =0; |
---|
| 541 | U nf = 0; |
---|
| 542 | Detach(bf); |
---|
| 543 | bf->mark=++markid; |
---|
| 544 | for(U i=0;i<3;++i) { |
---|
| 545 | nf+=BuildHorizon(markid,w,*bf->f[i],bf->e[i],cf,ff); } |
---|
| 546 | if(nf<=2) { break; } |
---|
| 547 | Link(cf,1,ff,2); |
---|
| 548 | } else break; |
---|
| 549 | } else break; |
---|
| 550 | } |
---|
| 551 | /* Extract contact */ |
---|
| 552 | if(bestface) |
---|
| 553 | { |
---|
| 554 | const Vector3 b(GetCoordinates(bestface)); |
---|
| 555 | normal = bestface->n; |
---|
| 556 | depth = Max<F>(0,bestface->d); |
---|
| 557 | for(U i=0;i<2;++i) |
---|
| 558 | { |
---|
| 559 | const F s(F(i?-1:1)); |
---|
| 560 | for(U j=0;j<3;++j) |
---|
| 561 | { |
---|
| 562 | features[i][j]=gjk->LocalSupport(s*bestface->v[j]->r,i); |
---|
| 563 | } |
---|
| 564 | } |
---|
| 565 | nearest[0] = features[0][0]*b.x()+features[0][1]*b.y()+features[0][2]*b.z(); |
---|
| 566 | nearest[1] = features[1][0]*b.x()+features[1][1]*b.y()+features[1][2]*b.z(); |
---|
| 567 | } else failed=true; |
---|
| 568 | sa->endBlock(sablock); |
---|
| 569 | return(depth); |
---|
| 570 | } |
---|
| 571 | }; |
---|
| 572 | } |
---|
| 573 | |
---|
| 574 | // |
---|
| 575 | // Api |
---|
| 576 | // |
---|
| 577 | |
---|
| 578 | using namespace gjkepa_impl; |
---|
| 579 | |
---|
| 580 | |
---|
| 581 | |
---|
| 582 | // |
---|
| 583 | bool btGjkEpaSolver::Collide(const btConvexShape *shape0,const btTransform &wtrs0, |
---|
| 584 | const btConvexShape *shape1,const btTransform &wtrs1, |
---|
| 585 | btScalar radialmargin, |
---|
| 586 | btStackAlloc* stackAlloc, |
---|
| 587 | sResults& results) |
---|
| 588 | { |
---|
| 589 | |
---|
| 590 | |
---|
| 591 | /* Initialize */ |
---|
| 592 | results.witnesses[0] = |
---|
| 593 | results.witnesses[1] = |
---|
| 594 | results.normal = Vector3(0,0,0); |
---|
| 595 | results.depth = 0; |
---|
| 596 | results.status = sResults::Separated; |
---|
| 597 | results.epa_iterations = 0; |
---|
| 598 | results.gjk_iterations = 0; |
---|
| 599 | /* Use GJK to locate origin */ |
---|
| 600 | GJK gjk(stackAlloc, |
---|
| 601 | wtrs0.getBasis(),wtrs0.getOrigin(),shape0, |
---|
| 602 | wtrs1.getBasis(),wtrs1.getOrigin(),shape1, |
---|
| 603 | radialmargin+EPA_accuracy); |
---|
| 604 | const Z collide(gjk.SearchOrigin()); |
---|
| 605 | results.gjk_iterations = static_cast<int>(gjk.iterations+1); |
---|
| 606 | if(collide) |
---|
| 607 | { |
---|
| 608 | /* Then EPA for penetration depth */ |
---|
| 609 | EPA epa(&gjk); |
---|
| 610 | const F pd(epa.EvaluatePD()); |
---|
| 611 | results.epa_iterations = static_cast<int>(epa.iterations+1); |
---|
| 612 | if(pd>0) |
---|
| 613 | { |
---|
| 614 | results.status = sResults::Penetrating; |
---|
| 615 | results.normal = epa.normal; |
---|
| 616 | results.depth = pd; |
---|
| 617 | results.witnesses[0] = epa.nearest[0]; |
---|
| 618 | results.witnesses[1] = epa.nearest[1]; |
---|
| 619 | return(true); |
---|
| 620 | } else { if(epa.failed) results.status=sResults::EPA_Failed; } |
---|
| 621 | } else { if(gjk.failed) results.status=sResults::GJK_Failed; } |
---|
| 622 | return(false); |
---|
| 623 | } |
---|
| 624 | |
---|
| 625 | |
---|
| 626 | |
---|
| 627 | |
---|
| 628 | |
---|