btGjkEpa2.cpp

Go to the documentation of this file.
00001 /*
00002 Bullet Continuous Collision Detection and Physics Library
00003 Copyright (c) 2003-2008 Erwin Coumans  http://continuousphysics.com/Bullet/
00004 
00005 This software is provided 'as-is', without any express or implied warranty.
00006 In no event will the authors be held liable for any damages arising from the
00007 use of this software.
00008 Permission is granted to anyone to use this software for any purpose,
00009 including commercial applications, and to alter it and redistribute it
00010 freely,
00011 subject to the following restrictions:
00012 
00013 1. The origin of this software must not be misrepresented; you must not
00014 claim that you wrote the original software. If you use this software in a
00015 product, an acknowledgment in the product documentation would be appreciated
00016 but is not required.
00017 2. Altered source versions must be plainly marked as such, and must not be
00018 misrepresented as being the original software.
00019 3. This notice may not be removed or altered from any source distribution.
00020 */
00021 
00022 /*
00023 GJK-EPA collision solver by Nathanael Presson, 2008
00024 */
00025 #include "BulletCollision/CollisionShapes/btConvexInternalShape.h"
00026 #include "BulletCollision/CollisionShapes/btSphereShape.h"
00027 #include "btGjkEpa2.h"
00028 
00029 #if defined(DEBUG) || defined (_DEBUG)
00030 #include <stdio.h> //for debug printf
00031 #ifdef __SPU__
00032 #include <spu_printf.h>
00033 #define printf spu_printf
00034 #endif //__SPU__
00035 #endif
00036 
00037 namespace gjkepa2_impl
00038 {
00039 
00040         // Config
00041 
00042         /* GJK  */ 
00043 #define GJK_MAX_ITERATIONS      128
00044 #define GJK_ACCURARY            ((btScalar)0.0001)
00045 #define GJK_MIN_DISTANCE        ((btScalar)0.0001)
00046 #define GJK_DUPLICATED_EPS      ((btScalar)0.0001)
00047 #define GJK_SIMPLEX2_EPS        ((btScalar)0.0)
00048 #define GJK_SIMPLEX3_EPS        ((btScalar)0.0)
00049 #define GJK_SIMPLEX4_EPS        ((btScalar)0.0)
00050 
00051         /* EPA  */ 
00052 #define EPA_MAX_VERTICES        64
00053 #define EPA_MAX_FACES           (EPA_MAX_VERTICES*2)
00054 #define EPA_MAX_ITERATIONS      255
00055 #define EPA_ACCURACY            ((btScalar)0.0001)
00056 #define EPA_FALLBACK            (10*EPA_ACCURACY)
00057 #define EPA_PLANE_EPS           ((btScalar)0.00001)
00058 #define EPA_INSIDE_EPS          ((btScalar)0.01)
00059 
00060 
00061         // Shorthands
00062         typedef unsigned int    U;
00063         typedef unsigned char   U1;
00064 
00065         // MinkowskiDiff
00066         struct  MinkowskiDiff
00067         {
00068                 const btConvexShape*    m_shapes[2];
00069                 btMatrix3x3                             m_toshape1;
00070                 btTransform                             m_toshape0;
00071 #ifdef __SPU__
00072                 bool                                    m_enableMargin;
00073 #else
00074                 btVector3                               (btConvexShape::*Ls)(const btVector3&) const;
00075 #endif//__SPU__
00076                 
00077 
00078                 MinkowskiDiff()
00079                 {
00080 
00081                 }
00082 #ifdef __SPU__
00083                         void                                    EnableMargin(bool enable)
00084                 {
00085                         m_enableMargin = enable;
00086                 }       
00087                 inline btVector3                Support0(const btVector3& d) const
00088                 {
00089                         if (m_enableMargin)
00090                         {
00091                                 return m_shapes[0]->localGetSupportVertexNonVirtual(d);
00092                         } else
00093                         {
00094                                 return m_shapes[0]->localGetSupportVertexWithoutMarginNonVirtual(d);
00095                         }
00096                 }
00097                 inline btVector3                Support1(const btVector3& d) const
00098                 {
00099                         if (m_enableMargin)
00100                         {
00101                                 return m_toshape0*(m_shapes[1]->localGetSupportVertexNonVirtual(m_toshape1*d));
00102                         } else
00103                         {
00104                                 return m_toshape0*(m_shapes[1]->localGetSupportVertexWithoutMarginNonVirtual(m_toshape1*d));
00105                         }
00106                 }
00107 #else
00108                 void                                    EnableMargin(bool enable)
00109                 {
00110                         if(enable)
00111                                 Ls=&btConvexShape::localGetSupportVertexNonVirtual;
00112                         else
00113                                 Ls=&btConvexShape::localGetSupportVertexWithoutMarginNonVirtual;
00114                 }       
00115                 inline btVector3                Support0(const btVector3& d) const
00116                 {
00117                         return(((m_shapes[0])->*(Ls))(d));
00118                 }
00119                 inline btVector3                Support1(const btVector3& d) const
00120                 {
00121                         return(m_toshape0*((m_shapes[1])->*(Ls))(m_toshape1*d));
00122                 }
00123 #endif //__SPU__
00124 
00125                 inline btVector3                Support(const btVector3& d) const
00126                 {
00127                         return(Support0(d)-Support1(-d));
00128                 }
00129                 btVector3                               Support(const btVector3& d,U index) const
00130                 {
00131                         if(index)
00132                                 return(Support1(d));
00133                         else
00134                                 return(Support0(d));
00135                 }
00136         };
00137 
00138         typedef MinkowskiDiff   tShape;
00139 
00140 
00141         // GJK
00142         struct  GJK
00143         {
00144                 /* Types                */ 
00145                 struct  sSV
00146                 {
00147                         btVector3       d,w;
00148                 };
00149                 struct  sSimplex
00150                 {
00151                         sSV*            c[4];
00152                         btScalar        p[4];
00153                         U                       rank;
00154                 };
00155                 struct  eStatus { enum _ {
00156                         Valid,
00157                         Inside,
00158                         Failed          };};
00159                         /* Fields               */ 
00160                         tShape                  m_shape;
00161                         btVector3               m_ray;
00162                         btScalar                m_distance;
00163                         sSimplex                m_simplices[2];
00164                         sSV                             m_store[4];
00165                         sSV*                    m_free[4];
00166                         U                               m_nfree;
00167                         U                               m_current;
00168                         sSimplex*               m_simplex;
00169                         eStatus::_              m_status;
00170                         /* Methods              */ 
00171                         GJK()
00172                         {
00173                                 Initialize();
00174                         }
00175                         void                            Initialize()
00176                         {
00177                                 m_ray           =       btVector3(0,0,0);
00178                                 m_nfree         =       0;
00179                                 m_status        =       eStatus::Failed;
00180                                 m_current       =       0;
00181                                 m_distance      =       0;
00182                         }
00183                         eStatus::_                      Evaluate(const tShape& shapearg,const btVector3& guess)
00184                         {
00185                                 U                       iterations=0;
00186                                 btScalar        sqdist=0;
00187                                 btScalar        alpha=0;
00188                                 btVector3       lastw[4];
00189                                 U                       clastw=0;
00190                                 /* Initialize solver            */ 
00191                                 m_free[0]                       =       &m_store[0];
00192                                 m_free[1]                       =       &m_store[1];
00193                                 m_free[2]                       =       &m_store[2];
00194                                 m_free[3]                       =       &m_store[3];
00195                                 m_nfree                         =       4;
00196                                 m_current                       =       0;
00197                                 m_status                        =       eStatus::Valid;
00198                                 m_shape                         =       shapearg;
00199                                 m_distance                      =       0;
00200                                 /* Initialize simplex           */ 
00201                                 m_simplices[0].rank     =       0;
00202                                 m_ray                           =       guess;
00203                                 const btScalar  sqrl=   m_ray.length2();
00204                                 appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
00205                                 m_simplices[0].p[0]     =       1;
00206                                 m_ray                           =       m_simplices[0].c[0]->w; 
00207                                 sqdist                          =       sqrl;
00208                                 lastw[0]                        =
00209                                         lastw[1]                        =
00210                                         lastw[2]                        =
00211                                         lastw[3]                        =       m_ray;
00212                                 /* Loop                                         */ 
00213                                 do      {
00214                                         const U         next=1-m_current;
00215                                         sSimplex&       cs=m_simplices[m_current];
00216                                         sSimplex&       ns=m_simplices[next];
00217                                         /* Check zero                                                   */ 
00218                                         const btScalar  rl=m_ray.length();
00219                                         if(rl<GJK_MIN_DISTANCE)
00220                                         {/* Touching or inside                          */ 
00221                                                 m_status=eStatus::Inside;
00222                                                 break;
00223                                         }
00224                                         /* Append new vertice in -'v' direction */ 
00225                                         appendvertice(cs,-m_ray);
00226                                         const btVector3&        w=cs.c[cs.rank-1]->w;
00227                                         bool                            found=false;
00228                                         for(U i=0;i<4;++i)
00229                                         {
00230                                                 if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
00231                                                 { found=true;break; }
00232                                         }
00233                                         if(found)
00234                                         {/* Return old simplex                          */ 
00235                                                 removevertice(m_simplices[m_current]);
00236                                                 break;
00237                                         }
00238                                         else
00239                                         {/* Update lastw                                        */ 
00240                                                 lastw[clastw=(clastw+1)&3]=w;
00241                                         }
00242                                         /* Check for termination                                */ 
00243                                         const btScalar  omega=btDot(m_ray,w)/rl;
00244                                         alpha=btMax(omega,alpha);
00245                                         if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
00246                                         {/* Return old simplex                          */ 
00247                                                 removevertice(m_simplices[m_current]);
00248                                                 break;
00249                                         }               
00250                                         /* Reduce simplex                                               */ 
00251                                         btScalar        weights[4];
00252                                         U                       mask=0;
00253                                         switch(cs.rank)
00254                                         {
00255                                         case    2:      sqdist=projectorigin(   cs.c[0]->w,
00256                                                                         cs.c[1]->w,
00257                                                                         weights,mask);break;
00258                                         case    3:      sqdist=projectorigin(   cs.c[0]->w,
00259                                                                         cs.c[1]->w,
00260                                                                         cs.c[2]->w,
00261                                                                         weights,mask);break;
00262                                         case    4:      sqdist=projectorigin(   cs.c[0]->w,
00263                                                                         cs.c[1]->w,
00264                                                                         cs.c[2]->w,
00265                                                                         cs.c[3]->w,
00266                                                                         weights,mask);break;
00267                                         }
00268                                         if(sqdist>=0)
00269                                         {/* Valid       */ 
00270                                                 ns.rank         =       0;
00271                                                 m_ray           =       btVector3(0,0,0);
00272                                                 m_current       =       next;
00273                                                 for(U i=0,ni=cs.rank;i<ni;++i)
00274                                                 {
00275                                                         if(mask&(1<<i))
00276                                                         {
00277                                                                 ns.c[ns.rank]           =       cs.c[i];
00278                                                                 ns.p[ns.rank++]         =       weights[i];
00279                                                                 m_ray                           +=      cs.c[i]->w*weights[i];
00280                                                         }
00281                                                         else
00282                                                         {
00283                                                                 m_free[m_nfree++]       =       cs.c[i];
00284                                                         }
00285                                                 }
00286                                                 if(mask==15) m_status=eStatus::Inside;
00287                                         }
00288                                         else
00289                                         {/* Return old simplex                          */ 
00290                                                 removevertice(m_simplices[m_current]);
00291                                                 break;
00292                                         }
00293                                         m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eStatus::Failed;
00294                                 } while(m_status==eStatus::Valid);
00295                                 m_simplex=&m_simplices[m_current];
00296                                 switch(m_status)
00297                                 {
00298                                 case    eStatus::Valid:         m_distance=m_ray.length();break;
00299                                 case    eStatus::Inside:        m_distance=0;break;
00300                                 default:
00301                                         {
00302                                         }
00303                                 }       
00304                                 return(m_status);
00305                         }
00306                         bool                                    EncloseOrigin()
00307                         {
00308                                 switch(m_simplex->rank)
00309                                 {
00310                                 case    1:
00311                                         {
00312                                                 for(U i=0;i<3;++i)
00313                                                 {
00314                                                         btVector3               axis=btVector3(0,0,0);
00315                                                         axis[i]=1;
00316                                                         appendvertice(*m_simplex, axis);
00317                                                         if(EncloseOrigin())     return(true);
00318                                                         removevertice(*m_simplex);
00319                                                         appendvertice(*m_simplex,-axis);
00320                                                         if(EncloseOrigin())     return(true);
00321                                                         removevertice(*m_simplex);
00322                                                 }
00323                                         }
00324                                         break;
00325                                 case    2:
00326                                         {
00327                                                 const btVector3 d=m_simplex->c[1]->w-m_simplex->c[0]->w;
00328                                                 for(U i=0;i<3;++i)
00329                                                 {
00330                                                         btVector3               axis=btVector3(0,0,0);
00331                                                         axis[i]=1;
00332                                                         const btVector3 p=btCross(d,axis);
00333                                                         if(p.length2()>0)
00334                                                         {
00335                                                                 appendvertice(*m_simplex, p);
00336                                                                 if(EncloseOrigin())     return(true);
00337                                                                 removevertice(*m_simplex);
00338                                                                 appendvertice(*m_simplex,-p);
00339                                                                 if(EncloseOrigin())     return(true);
00340                                                                 removevertice(*m_simplex);
00341                                                         }
00342                                                 }
00343                                         }
00344                                         break;
00345                                 case    3:
00346                                         {
00347                                                 const btVector3 n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
00348                                                         m_simplex->c[2]->w-m_simplex->c[0]->w);
00349                                                 if(n.length2()>0)
00350                                                 {
00351                                                         appendvertice(*m_simplex,n);
00352                                                         if(EncloseOrigin())     return(true);
00353                                                         removevertice(*m_simplex);
00354                                                         appendvertice(*m_simplex,-n);
00355                                                         if(EncloseOrigin())     return(true);
00356                                                         removevertice(*m_simplex);
00357                                                 }
00358                                         }
00359                                         break;
00360                                 case    4:
00361                                         {
00362                                                 if(btFabs(det(  m_simplex->c[0]->w-m_simplex->c[3]->w,
00363                                                         m_simplex->c[1]->w-m_simplex->c[3]->w,
00364                                                         m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
00365                                                         return(true);
00366                                         }
00367                                         break;
00368                                 }
00369                                 return(false);
00370                         }
00371                         /* Internals    */ 
00372                         void                            getsupport(const btVector3& d,sSV& sv) const
00373                         {
00374                                 sv.d    =       d/d.length();
00375                                 sv.w    =       m_shape.Support(sv.d);
00376                         }
00377                         void                            removevertice(sSimplex& simplex)
00378                         {
00379                                 m_free[m_nfree++]=simplex.c[--simplex.rank];
00380                         }
00381                         void                            appendvertice(sSimplex& simplex,const btVector3& v)
00382                         {
00383                                 simplex.p[simplex.rank]=0;
00384                                 simplex.c[simplex.rank]=m_free[--m_nfree];
00385                                 getsupport(v,*simplex.c[simplex.rank++]);
00386                         }
00387                         static btScalar         det(const btVector3& a,const btVector3& b,const btVector3& c)
00388                         {
00389                                 return( a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
00390                                         a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
00391                                         a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
00392                         }
00393                         static btScalar         projectorigin(  const btVector3& a,
00394                                 const btVector3& b,
00395                                 btScalar* w,U& m)
00396                         {
00397                                 const btVector3 d=b-a;
00398                                 const btScalar  l=d.length2();
00399                                 if(l>GJK_SIMPLEX2_EPS)
00400                                 {
00401                                         const btScalar  t(l>0?-btDot(a,d)/l:0);
00402                                         if(t>=1)                { w[0]=0;w[1]=1;m=2;return(b.length2()); }
00403                                         else if(t<=0)   { w[0]=1;w[1]=0;m=1;return(a.length2()); }
00404                                         else                    { w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
00405                                 }
00406                                 return(-1);
00407                         }
00408                         static btScalar         projectorigin(  const btVector3& a,
00409                                 const btVector3& b,
00410                                 const btVector3& c,
00411                                 btScalar* w,U& m)
00412                         {
00413                                 static const U          imd3[]={1,2,0};
00414                                 const btVector3*        vt[]={&a,&b,&c};
00415                                 const btVector3         dl[]={a-b,b-c,c-a};
00416                                 const btVector3         n=btCross(dl[0],dl[1]);
00417                                 const btScalar          l=n.length2();
00418                                 if(l>GJK_SIMPLEX3_EPS)
00419                                 {
00420                                         btScalar        mindist=-1;
00421                                         btScalar        subw[2]={0.f,0.f};
00422                                         U                       subm(0);
00423                                         for(U i=0;i<3;++i)
00424                                         {
00425                                                 if(btDot(*vt[i],btCross(dl[i],n))>0)
00426                                                 {
00427                                                         const U                 j=imd3[i];
00428                                                         const btScalar  subd(projectorigin(*vt[i],*vt[j],subw,subm));
00429                                                         if((mindist<0)||(subd<mindist))
00430                                                         {
00431                                                                 mindist         =       subd;
00432                                                                 m                       =       static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
00433                                                                 w[i]            =       subw[0];
00434                                                                 w[j]            =       subw[1];
00435                                                                 w[imd3[j]]      =       0;                              
00436                                                         }
00437                                                 }
00438                                         }
00439                                         if(mindist<0)
00440                                         {
00441                                                 const btScalar  d=btDot(a,n);   
00442                                                 const btScalar  s=btSqrt(l);
00443                                                 const btVector3 p=n*(d/l);
00444                                                 mindist =       p.length2();
00445                                                 m               =       7;
00446                                                 w[0]    =       (btCross(dl[1],b-p)).length()/s;
00447                                                 w[1]    =       (btCross(dl[2],c-p)).length()/s;
00448                                                 w[2]    =       1-(w[0]+w[1]);
00449                                         }
00450                                         return(mindist);
00451                                 }
00452                                 return(-1);
00453                         }
00454                         static btScalar         projectorigin(  const btVector3& a,
00455                                 const btVector3& b,
00456                                 const btVector3& c,
00457                                 const btVector3& d,
00458                                 btScalar* w,U& m)
00459                         {
00460                                 static const U          imd3[]={1,2,0};
00461                                 const btVector3*        vt[]={&a,&b,&c,&d};
00462                                 const btVector3         dl[]={a-d,b-d,c-d};
00463                                 const btScalar          vl=det(dl[0],dl[1],dl[2]);
00464                                 const bool                      ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
00465                                 if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
00466                                 {
00467                                         btScalar        mindist=-1;
00468                                         btScalar        subw[3]={0.f,0.f,0.f};
00469                                         U                       subm(0);
00470                                         for(U i=0;i<3;++i)
00471                                         {
00472                                                 const U                 j=imd3[i];
00473                                                 const btScalar  s=vl*btDot(d,btCross(dl[i],dl[j]));
00474                                                 if(s>0)
00475                                                 {
00476                                                         const btScalar  subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
00477                                                         if((mindist<0)||(subd<mindist))
00478                                                         {
00479                                                                 mindist         =       subd;
00480                                                                 m                       =       static_cast<U>((subm&1?1<<i:0)+
00481                                                                         (subm&2?1<<j:0)+
00482                                                                         (subm&4?8:0));
00483                                                                 w[i]            =       subw[0];
00484                                                                 w[j]            =       subw[1];
00485                                                                 w[imd3[j]]      =       0;
00486                                                                 w[3]            =       subw[2];
00487                                                         }
00488                                                 }
00489                                         }
00490                                         if(mindist<0)
00491                                         {
00492                                                 mindist =       0;
00493                                                 m               =       15;
00494                                                 w[0]    =       det(c,b,d)/vl;
00495                                                 w[1]    =       det(a,c,d)/vl;
00496                                                 w[2]    =       det(b,a,d)/vl;
00497                                                 w[3]    =       1-(w[0]+w[1]+w[2]);
00498                                         }
00499                                         return(mindist);
00500                                 }
00501                                 return(-1);
00502                         }
00503         };
00504 
00505         // EPA
00506         struct  EPA
00507         {
00508                 /* Types                */ 
00509                 typedef GJK::sSV        sSV;
00510                 struct  sFace
00511                 {
00512                         btVector3       n;
00513                         btScalar        d;
00514                         btScalar        p;
00515                         sSV*            c[3];
00516                         sFace*          f[3];
00517                         sFace*          l[2];
00518                         U1                      e[3];
00519                         U1                      pass;
00520                 };
00521                 struct  sList
00522                 {
00523                         sFace*          root;
00524                         U                       count;
00525                         sList() : root(0),count(0)      {}
00526                 };
00527                 struct  sHorizon
00528                 {
00529                         sFace*          cf;
00530                         sFace*          ff;
00531                         U                       nf;
00532                         sHorizon() : cf(0),ff(0),nf(0)  {}
00533                 };
00534                 struct  eStatus { enum _ {
00535                         Valid,
00536                         Touching,
00537                         Degenerated,
00538                         NonConvex,
00539                         InvalidHull,            
00540                         OutOfFaces,
00541                         OutOfVertices,
00542                         AccuraryReached,
00543                         FallBack,
00544                         Failed          };};
00545                         /* Fields               */ 
00546                         eStatus::_              m_status;
00547                         GJK::sSimplex   m_result;
00548                         btVector3               m_normal;
00549                         btScalar                m_depth;
00550                         sSV                             m_sv_store[EPA_MAX_VERTICES];
00551                         sFace                   m_fc_store[EPA_MAX_FACES];
00552                         U                               m_nextsv;
00553                         sList                   m_hull;
00554                         sList                   m_stock;
00555                         /* Methods              */ 
00556                         EPA()
00557                         {
00558                                 Initialize();   
00559                         }
00560 
00561 
00562                         static inline void              bind(sFace* fa,U ea,sFace* fb,U eb)
00563                         {
00564                                 fa->e[ea]=(U1)eb;fa->f[ea]=fb;
00565                                 fb->e[eb]=(U1)ea;fb->f[eb]=fa;
00566                         }
00567                         static inline void              append(sList& list,sFace* face)
00568                         {
00569                                 face->l[0]      =       0;
00570                                 face->l[1]      =       list.root;
00571                                 if(list.root) list.root->l[0]=face;
00572                                 list.root       =       face;
00573                                 ++list.count;
00574                         }
00575                         static inline void              remove(sList& list,sFace* face)
00576                         {
00577                                 if(face->l[1]) face->l[1]->l[0]=face->l[0];
00578                                 if(face->l[0]) face->l[0]->l[1]=face->l[1];
00579                                 if(face==list.root) list.root=face->l[1];
00580                                 --list.count;
00581                         }
00582 
00583 
00584                         void                            Initialize()
00585                         {
00586                                 m_status        =       eStatus::Failed;
00587                                 m_normal        =       btVector3(0,0,0);
00588                                 m_depth         =       0;
00589                                 m_nextsv        =       0;
00590                                 for(U i=0;i<EPA_MAX_FACES;++i)
00591                                 {
00592                                         append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
00593                                 }
00594                         }
00595                         eStatus::_                      Evaluate(GJK& gjk,const btVector3& guess)
00596                         {
00597                                 GJK::sSimplex&  simplex=*gjk.m_simplex;
00598                                 if((simplex.rank>1)&&gjk.EncloseOrigin())
00599                                 {
00600 
00601                                         /* Clean up                             */ 
00602                                         while(m_hull.root)
00603                                         {
00604                                                 sFace*  f = m_hull.root;
00605                                                 remove(m_hull,f);
00606                                                 append(m_stock,f);
00607                                         }
00608                                         m_status        =       eStatus::Valid;
00609                                         m_nextsv        =       0;
00610                                         /* Orient simplex               */ 
00611                                         if(gjk.det(     simplex.c[0]->w-simplex.c[3]->w,
00612                                                 simplex.c[1]->w-simplex.c[3]->w,
00613                                                 simplex.c[2]->w-simplex.c[3]->w)<0)
00614                                         {
00615                                                 btSwap(simplex.c[0],simplex.c[1]);
00616                                                 btSwap(simplex.p[0],simplex.p[1]);
00617                                         }
00618                                         /* Build initial hull   */ 
00619                                         sFace*  tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
00620                                                 newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
00621                                                 newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
00622                                                 newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
00623                                         if(m_hull.count==4)
00624                                         {
00625                                                 sFace*          best=findbest();
00626                                                 sFace           outer=*best;
00627                                                 U                       pass=0;
00628                                                 U                       iterations=0;
00629                                                 bind(tetra[0],0,tetra[1],0);
00630                                                 bind(tetra[0],1,tetra[2],0);
00631                                                 bind(tetra[0],2,tetra[3],0);
00632                                                 bind(tetra[1],1,tetra[3],2);
00633                                                 bind(tetra[1],2,tetra[2],1);
00634                                                 bind(tetra[2],2,tetra[3],1);
00635                                                 m_status=eStatus::Valid;
00636                                                 for(;iterations<EPA_MAX_ITERATIONS;++iterations)
00637                                                 {
00638                                                         if(m_nextsv<EPA_MAX_VERTICES)
00639                                                         {       
00640                                                                 sHorizon                horizon;
00641                                                                 sSV*                    w=&m_sv_store[m_nextsv++];
00642                                                                 bool                    valid=true;                                     
00643                                                                 best->pass      =       (U1)(++pass);
00644                                                                 gjk.getsupport(best->n,*w);
00645                                                                 const btScalar  wdist=btDot(best->n,w->w)-best->d;
00646                                                                 if(wdist>EPA_ACCURACY)
00647                                                                 {
00648                                                                         for(U j=0;(j<3)&&valid;++j)
00649                                                                         {
00650                                                                                 valid&=expand(  pass,w,
00651                                                                                         best->f[j],best->e[j],
00652                                                                                         horizon);
00653                                                                         }
00654                                                                         if(valid&&(horizon.nf>=3))
00655                                                                         {
00656                                                                                 bind(horizon.cf,1,horizon.ff,2);
00657                                                                                 remove(m_hull,best);
00658                                                                                 append(m_stock,best);
00659                                                                                 best=findbest();
00660                                                                                 if(best->p>=outer.p) outer=*best;
00661                                                                         } else { m_status=eStatus::InvalidHull;break; }
00662                                                                 } else { m_status=eStatus::AccuraryReached;break; }
00663                                                         } else { m_status=eStatus::OutOfVertices;break; }
00664                                                 }
00665                                                 const btVector3 projection=outer.n*outer.d;
00666                                                 m_normal        =       outer.n;
00667                                                 m_depth         =       outer.d;
00668                                                 m_result.rank   =       3;
00669                                                 m_result.c[0]   =       outer.c[0];
00670                                                 m_result.c[1]   =       outer.c[1];
00671                                                 m_result.c[2]   =       outer.c[2];
00672                                                 m_result.p[0]   =       btCross(        outer.c[1]->w-projection,
00673                                                         outer.c[2]->w-projection).length();
00674                                                 m_result.p[1]   =       btCross(        outer.c[2]->w-projection,
00675                                                         outer.c[0]->w-projection).length();
00676                                                 m_result.p[2]   =       btCross(        outer.c[0]->w-projection,
00677                                                         outer.c[1]->w-projection).length();
00678                                                 const btScalar  sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
00679                                                 m_result.p[0]   /=      sum;
00680                                                 m_result.p[1]   /=      sum;
00681                                                 m_result.p[2]   /=      sum;
00682                                                 return(m_status);
00683                                         }
00684                                 }
00685                                 /* Fallback             */ 
00686                                 m_status        =       eStatus::FallBack;
00687                                 m_normal        =       -guess;
00688                                 const btScalar  nl=m_normal.length();
00689                                 if(nl>0)
00690                                         m_normal        =       m_normal/nl;
00691                                 else
00692                                         m_normal        =       btVector3(1,0,0);
00693                                 m_depth =       0;
00694                                 m_result.rank=1;
00695                                 m_result.c[0]=simplex.c[0];
00696                                 m_result.p[0]=1;        
00697                                 return(m_status);
00698                         }
00699                         sFace*                          newface(sSV* a,sSV* b,sSV* c,bool forced)
00700                         {
00701                                 if(m_stock.root)
00702                                 {
00703                                         sFace*  face=m_stock.root;
00704                                         remove(m_stock,face);
00705                                         append(m_hull,face);
00706                                         face->pass      =       0;
00707                                         face->c[0]      =       a;
00708                                         face->c[1]      =       b;
00709                                         face->c[2]      =       c;
00710                                         face->n         =       btCross(b->w-a->w,c->w-a->w);
00711                                         const btScalar  l=face->n.length();
00712                                         const bool              v=l>EPA_ACCURACY;
00713                                         face->p         =       btMin(btMin(
00714                                                 btDot(a->w,btCross(face->n,a->w-b->w)),
00715                                                 btDot(b->w,btCross(face->n,b->w-c->w))),
00716                                                 btDot(c->w,btCross(face->n,c->w-a->w))) /
00717                                                 (v?l:1);
00718                                         face->p         =       face->p>=-EPA_INSIDE_EPS?0:face->p;
00719                                         if(v)
00720                                         {
00721                                                 face->d         =       btDot(a->w,face->n)/l;
00722                                                 face->n         /=      l;
00723                                                 if(forced||(face->d>=-EPA_PLANE_EPS))
00724                                                 {
00725                                                         return(face);
00726                                                 } else m_status=eStatus::NonConvex;
00727                                         } else m_status=eStatus::Degenerated;
00728                                         remove(m_hull,face);
00729                                         append(m_stock,face);
00730                                         return(0);
00731                                 }
00732                                 m_status=m_stock.root?eStatus::OutOfVertices:eStatus::OutOfFaces;
00733                                 return(0);
00734                         }
00735                         sFace*                          findbest()
00736                         {
00737                                 sFace*          minf=m_hull.root;
00738                                 btScalar        mind=minf->d*minf->d;
00739                                 btScalar        maxp=minf->p;
00740                                 for(sFace* f=minf->l[1];f;f=f->l[1])
00741                                 {
00742                                         const btScalar  sqd=f->d*f->d;
00743                                         if((f->p>=maxp)&&(sqd<mind))
00744                                         {
00745                                                 minf=f;
00746                                                 mind=sqd;
00747                                                 maxp=f->p;
00748                                         }
00749                                 }
00750                                 return(minf);
00751                         }
00752                         bool                            expand(U pass,sSV* w,sFace* f,U e,sHorizon& horizon)
00753                         {
00754                                 static const U  i1m3[]={1,2,0};
00755                                 static const U  i2m3[]={2,0,1};
00756                                 if(f->pass!=pass)
00757                                 {
00758                                         const U e1=i1m3[e];
00759                                         if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
00760                                         {
00761                                                 sFace*  nf=newface(f->c[e1],f->c[e],w,false);
00762                                                 if(nf)
00763                                                 {
00764                                                         bind(nf,0,f,e);
00765                                                         if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
00766                                                         horizon.cf=nf;
00767                                                         ++horizon.nf;
00768                                                         return(true);
00769                                                 }
00770                                         }
00771                                         else
00772                                         {
00773                                                 const U e2=i2m3[e];
00774                                                 f->pass         =       (U1)pass;
00775                                                 if(     expand(pass,w,f->f[e1],f->e[e1],horizon)&&
00776                                                         expand(pass,w,f->f[e2],f->e[e2],horizon))
00777                                                 {
00778                                                         remove(m_hull,f);
00779                                                         append(m_stock,f);
00780                                                         return(true);
00781                                                 }
00782                                         }
00783                                 }
00784                                 return(false);
00785                         }
00786 
00787         };
00788 
00789         //
00790         static void     Initialize(     const btConvexShape* shape0,const btTransform& wtrs0,
00791                 const btConvexShape* shape1,const btTransform& wtrs1,
00792                 btGjkEpaSolver2::sResults& results,
00793                 tShape& shape,
00794                 bool withmargins)
00795         {
00796                 /* Results              */ 
00797                 results.witnesses[0]    =
00798                         results.witnesses[1]    =       btVector3(0,0,0);
00799                 results.status                  =       btGjkEpaSolver2::sResults::Separated;
00800                 /* Shape                */ 
00801                 shape.m_shapes[0]               =       shape0;
00802                 shape.m_shapes[1]               =       shape1;
00803                 shape.m_toshape1                =       wtrs1.getBasis().transposeTimes(wtrs0.getBasis());
00804                 shape.m_toshape0                =       wtrs0.inverseTimes(wtrs1);
00805                 shape.EnableMargin(withmargins);
00806         }
00807 
00808 }
00809 
00810 //
00811 // Api
00812 //
00813 
00814 using namespace gjkepa2_impl;
00815 
00816 //
00817 int                     btGjkEpaSolver2::StackSizeRequirement()
00818 {
00819         return(sizeof(GJK)+sizeof(EPA));
00820 }
00821 
00822 //
00823 bool            btGjkEpaSolver2::Distance(      const btConvexShape*    shape0,
00824                                                                           const btTransform&            wtrs0,
00825                                                                           const btConvexShape*  shape1,
00826                                                                           const btTransform&            wtrs1,
00827                                                                           const btVector3&              guess,
00828                                                                           sResults&                             results)
00829 {
00830         tShape                  shape;
00831         Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,false);
00832         GJK                             gjk;
00833         GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,guess);
00834         if(gjk_status==GJK::eStatus::Valid)
00835         {
00836                 btVector3       w0=btVector3(0,0,0);
00837                 btVector3       w1=btVector3(0,0,0);
00838                 for(U i=0;i<gjk.m_simplex->rank;++i)
00839                 {
00840                         const btScalar  p=gjk.m_simplex->p[i];
00841                         w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
00842                         w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
00843                 }
00844                 results.witnesses[0]    =       wtrs0*w0;
00845                 results.witnesses[1]    =       wtrs0*w1;
00846                 results.normal                  =       w0-w1;
00847                 results.distance                =       results.normal.length();
00848                 results.normal                  /=      results.distance>GJK_MIN_DISTANCE?results.distance:1;
00849                 return(true);
00850         }
00851         else
00852         {
00853                 results.status  =       gjk_status==GJK::eStatus::Inside?
00854                         sResults::Penetrating   :
00855                 sResults::GJK_Failed    ;
00856                 return(false);
00857         }
00858 }
00859 
00860 //
00861 bool    btGjkEpaSolver2::Penetration(   const btConvexShape*    shape0,
00862                                                                          const btTransform&             wtrs0,
00863                                                                          const btConvexShape*   shape1,
00864                                                                          const btTransform&             wtrs1,
00865                                                                          const btVector3&               guess,
00866                                                                          sResults&                              results,
00867                                                                          bool                                   usemargins)
00868 {
00869         tShape                  shape;
00870         Initialize(shape0,wtrs0,shape1,wtrs1,results,shape,usemargins);
00871         GJK                             gjk;    
00872         GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,-guess);
00873         switch(gjk_status)
00874         {
00875         case    GJK::eStatus::Inside:
00876                 {
00877                         EPA                             epa;
00878                         EPA::eStatus::_ epa_status=epa.Evaluate(gjk,-guess);
00879                         if(epa_status!=EPA::eStatus::Failed)
00880                         {
00881                                 btVector3       w0=btVector3(0,0,0);
00882                                 for(U i=0;i<epa.m_result.rank;++i)
00883                                 {
00884                                         w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
00885                                 }
00886                                 results.status                  =       sResults::Penetrating;
00887                                 results.witnesses[0]    =       wtrs0*w0;
00888                                 results.witnesses[1]    =       wtrs0*(w0-epa.m_normal*epa.m_depth);
00889                                 results.normal                  =       -epa.m_normal;
00890                                 results.distance                =       -epa.m_depth;
00891                                 return(true);
00892                         } else results.status=sResults::EPA_Failed;
00893                 }
00894                 break;
00895         case    GJK::eStatus::Failed:
00896                 results.status=sResults::GJK_Failed;
00897                 break;
00898                 default:
00899                                         {
00900                                         }
00901         }
00902         return(false);
00903 }
00904 
00905 #ifndef __SPU__
00906 //
00907 btScalar        btGjkEpaSolver2::SignedDistance(const btVector3& position,
00908                                                                                         btScalar margin,
00909                                                                                         const btConvexShape* shape0,
00910                                                                                         const btTransform& wtrs0,
00911                                                                                         sResults& results)
00912 {
00913         tShape                  shape;
00914         btSphereShape   shape1(margin);
00915         btTransform             wtrs1(btQuaternion(0,0,0,1),position);
00916         Initialize(shape0,wtrs0,&shape1,wtrs1,results,shape,false);
00917         GJK                             gjk;    
00918         GJK::eStatus::_ gjk_status=gjk.Evaluate(shape,btVector3(1,1,1));
00919         if(gjk_status==GJK::eStatus::Valid)
00920         {
00921                 btVector3       w0=btVector3(0,0,0);
00922                 btVector3       w1=btVector3(0,0,0);
00923                 for(U i=0;i<gjk.m_simplex->rank;++i)
00924                 {
00925                         const btScalar  p=gjk.m_simplex->p[i];
00926                         w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
00927                         w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
00928                 }
00929                 results.witnesses[0]    =       wtrs0*w0;
00930                 results.witnesses[1]    =       wtrs0*w1;
00931                 const btVector3 delta=  results.witnesses[1]-
00932                         results.witnesses[0];
00933                 const btScalar  margin= shape0->getMarginNonVirtual()+
00934                         shape1.getMarginNonVirtual();
00935                 const btScalar  length= delta.length(); 
00936                 results.normal                  =       delta/length;
00937                 results.witnesses[0]    +=      results.normal*margin;
00938                 return(length-margin);
00939         }
00940         else
00941         {
00942                 if(gjk_status==GJK::eStatus::Inside)
00943                 {
00944                         if(Penetration(shape0,wtrs0,&shape1,wtrs1,gjk.m_ray,results))
00945                         {
00946                                 const btVector3 delta=  results.witnesses[0]-
00947                                         results.witnesses[1];
00948                                 const btScalar  length= delta.length();
00949                                 if (length >= SIMD_EPSILON)
00950                                         results.normal  =       delta/length;                   
00951                                 return(-length);
00952                         }
00953                 }       
00954         }
00955         return(SIMD_INFINITY);
00956 }
00957 
00958 //
00959 bool    btGjkEpaSolver2::SignedDistance(const btConvexShape*    shape0,
00960                                                                                 const btTransform&              wtrs0,
00961                                                                                 const btConvexShape*    shape1,
00962                                                                                 const btTransform&              wtrs1,
00963                                                                                 const btVector3&                guess,
00964                                                                                 sResults&                               results)
00965 {
00966         if(!Distance(shape0,wtrs0,shape1,wtrs1,guess,results))
00967                 return(Penetration(shape0,wtrs0,shape1,wtrs1,guess,results,false));
00968         else
00969                 return(true);
00970 }
00971 #endif //__SPU__
00972 
00973 /* Symbols cleanup              */ 
00974 
00975 #undef GJK_MAX_ITERATIONS
00976 #undef GJK_ACCURARY
00977 #undef GJK_MIN_DISTANCE
00978 #undef GJK_DUPLICATED_EPS
00979 #undef GJK_SIMPLEX2_EPS
00980 #undef GJK_SIMPLEX3_EPS
00981 #undef GJK_SIMPLEX4_EPS
00982 
00983 #undef EPA_MAX_VERTICES
00984 #undef EPA_MAX_FACES
00985 #undef EPA_MAX_ITERATIONS
00986 #undef EPA_ACCURACY
00987 #undef EPA_FALLBACK
00988 #undef EPA_PLANE_EPS
00989 #undef EPA_INSIDE_EPS

Generated on Mon Feb 15 22:17:04 2010 for Bullet Collision Detection & Physics Library by  doxygen 1.6.1