Home | History | Annotate | Download | only in NarrowPhaseCollision
      1 /*
      2 Bullet Continuous Collision Detection and Physics Library
      3 Copyright (c) 2003-2014 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 Initial GJK-EPA collision solver by Nathanael Presson, 2008
     24 Improvements and refactoring by Erwin Coumans, 2008-2014
     25 */
     26 #ifndef BT_GJK_EPA3_H
     27 #define BT_GJK_EPA3_H
     28 
     29 #include "LinearMath/btTransform.h"
     30 #include "btGjkCollisionDescription.h"
     31 
     32 
     33 
     34 struct	btGjkEpaSolver3
     35 {
     36 struct	sResults
     37 	{
     38 	enum eStatus
     39 		{
     40 		Separated,		/* Shapes doesnt penetrate												*/
     41 		Penetrating,	/* Shapes are penetrating												*/
     42 		GJK_Failed,		/* GJK phase fail, no big issue, shapes are probably just 'touching'	*/
     43 		EPA_Failed		/* EPA phase fail, bigger problem, need to save parameters, and debug	*/
     44 		}		status;
     45 	btVector3	witnesses[2];
     46 	btVector3	normal;
     47 	btScalar	distance;
     48 	};
     49 
     50 
     51 };
     52 
     53 
     54 
     55 #if defined(DEBUG) || defined (_DEBUG)
     56 #include <stdio.h> //for debug printf
     57 #ifdef __SPU__
     58 #include <spu_printf.h>
     59 #define printf spu_printf
     60 #endif //__SPU__
     61 #endif
     62 
     63 
     64 
     65     // Config
     66 
     67     /* GJK	*/
     68 #define GJK_MAX_ITERATIONS	128
     69 #define GJK_ACCURARY		((btScalar)0.0001)
     70 #define GJK_MIN_DISTANCE	((btScalar)0.0001)
     71 #define GJK_DUPLICATED_EPS	((btScalar)0.0001)
     72 #define GJK_SIMPLEX2_EPS	((btScalar)0.0)
     73 #define GJK_SIMPLEX3_EPS	((btScalar)0.0)
     74 #define GJK_SIMPLEX4_EPS	((btScalar)0.0)
     75 
     76     /* EPA	*/
     77 #define EPA_MAX_VERTICES	64
     78 #define EPA_MAX_FACES		(EPA_MAX_VERTICES*2)
     79 #define EPA_MAX_ITERATIONS	255
     80 #define EPA_ACCURACY		((btScalar)0.0001)
     81 #define EPA_FALLBACK		(10*EPA_ACCURACY)
     82 #define EPA_PLANE_EPS		((btScalar)0.00001)
     83 #define EPA_INSIDE_EPS		((btScalar)0.01)
     84 
     85 
     86     // Shorthands
     87     typedef unsigned int	U;
     88     typedef unsigned char	U1;
     89 
     90     // MinkowskiDiff
     91     template <typename btConvexTemplate>
     92     struct	MinkowskiDiff
     93     {
     94         const btConvexTemplate* m_convexAPtr;
     95         const btConvexTemplate* m_convexBPtr;
     96 
     97         btMatrix3x3				m_toshape1;
     98         btTransform				m_toshape0;
     99 
    100         bool					m_enableMargin;
    101 
    102 
    103         MinkowskiDiff(const btConvexTemplate& a, const btConvexTemplate& b)
    104         :m_convexAPtr(&a),
    105         m_convexBPtr(&b)
    106         {
    107         }
    108 
    109         void					EnableMargin(bool enable)
    110         {
    111             m_enableMargin = enable;
    112         }
    113         inline btVector3		Support0(const btVector3& d) const
    114         {
    115             return m_convexAPtr->getLocalSupportWithMargin(d);
    116         }
    117         inline btVector3		Support1(const btVector3& d) const
    118         {
    119             return m_toshape0*m_convexBPtr->getLocalSupportWithMargin(m_toshape1*d);
    120         }
    121 
    122 
    123         inline btVector3		Support(const btVector3& d) const
    124         {
    125             return(Support0(d)-Support1(-d));
    126         }
    127         btVector3				Support(const btVector3& d,U index) const
    128         {
    129             if(index)
    130                 return(Support1(d));
    131             else
    132                 return(Support0(d));
    133         }
    134     };
    135 
    136 enum	eGjkStatus
    137 {
    138     eGjkValid,
    139     eGjkInside,
    140     eGjkFailed
    141 };
    142 
    143     // GJK
    144     template <typename btConvexTemplate>
    145     struct	GJK
    146     {
    147         /* Types		*/
    148         struct	sSV
    149         {
    150             btVector3	d,w;
    151         };
    152         struct	sSimplex
    153         {
    154             sSV*		c[4];
    155             btScalar	p[4];
    156             U			rank;
    157         };
    158 
    159         /* Fields		*/
    160 
    161         MinkowskiDiff<btConvexTemplate>			m_shape;
    162         btVector3		m_ray;
    163         btScalar		m_distance;
    164         sSimplex		m_simplices[2];
    165         sSV				m_store[4];
    166         sSV*			m_free[4];
    167         U				m_nfree;
    168         U				m_current;
    169         sSimplex*		m_simplex;
    170         eGjkStatus      m_status;
    171         /* Methods		*/
    172 
    173         GJK(const btConvexTemplate& a, const btConvexTemplate& b)
    174         :m_shape(a,b)
    175         {
    176             Initialize();
    177         }
    178         void				Initialize()
    179         {
    180             m_ray		=	btVector3(0,0,0);
    181             m_nfree		=	0;
    182             m_status	=	eGjkFailed;
    183             m_current	=	0;
    184             m_distance	=	0;
    185         }
    186         eGjkStatus			Evaluate(const MinkowskiDiff<btConvexTemplate>& shapearg,const btVector3& guess)
    187         {
    188             U			iterations=0;
    189             btScalar	sqdist=0;
    190             btScalar	alpha=0;
    191             btVector3	lastw[4];
    192             U			clastw=0;
    193             /* Initialize solver		*/
    194             m_free[0]			=	&m_store[0];
    195             m_free[1]			=	&m_store[1];
    196             m_free[2]			=	&m_store[2];
    197             m_free[3]			=	&m_store[3];
    198             m_nfree				=	4;
    199             m_current			=	0;
    200             m_status			=	eGjkValid;
    201             m_shape				=	shapearg;
    202             m_distance			=	0;
    203             /* Initialize simplex		*/
    204             m_simplices[0].rank	=	0;
    205             m_ray				=	guess;
    206             const btScalar	sqrl=	m_ray.length2();
    207             appendvertice(m_simplices[0],sqrl>0?-m_ray:btVector3(1,0,0));
    208             m_simplices[0].p[0]	=	1;
    209             m_ray				=	m_simplices[0].c[0]->w;
    210             sqdist				=	sqrl;
    211             lastw[0]			=
    212             lastw[1]			=
    213             lastw[2]			=
    214             lastw[3]			=	m_ray;
    215             /* Loop						*/
    216             do	{
    217                 const U		next=1-m_current;
    218                 sSimplex&	cs=m_simplices[m_current];
    219                 sSimplex&	ns=m_simplices[next];
    220                 /* Check zero							*/
    221                 const btScalar	rl=m_ray.length();
    222                 if(rl<GJK_MIN_DISTANCE)
    223                 {/* Touching or inside				*/
    224                     m_status=eGjkInside;
    225                     break;
    226                 }
    227                 /* Append new vertice in -'v' direction	*/
    228                 appendvertice(cs,-m_ray);
    229                 const btVector3&	w=cs.c[cs.rank-1]->w;
    230                 bool				found=false;
    231                 for(U i=0;i<4;++i)
    232                 {
    233                     if((w-lastw[i]).length2()<GJK_DUPLICATED_EPS)
    234                     { found=true;break; }
    235                 }
    236                 if(found)
    237                 {/* Return old simplex				*/
    238                     removevertice(m_simplices[m_current]);
    239                     break;
    240                 }
    241                 else
    242                 {/* Update lastw					*/
    243                     lastw[clastw=(clastw+1)&3]=w;
    244                 }
    245                 /* Check for termination				*/
    246                 const btScalar	omega=btDot(m_ray,w)/rl;
    247                 alpha=btMax(omega,alpha);
    248                 if(((rl-alpha)-(GJK_ACCURARY*rl))<=0)
    249                 {/* Return old simplex				*/
    250                     removevertice(m_simplices[m_current]);
    251                     break;
    252                 }
    253                 /* Reduce simplex						*/
    254                 btScalar	weights[4];
    255                 U			mask=0;
    256                 switch(cs.rank)
    257                 {
    258                     case	2:	sqdist=projectorigin(	cs.c[0]->w,
    259                                                      cs.c[1]->w,
    260                                                      weights,mask);break;
    261                     case	3:	sqdist=projectorigin(	cs.c[0]->w,
    262                                                      cs.c[1]->w,
    263                                                      cs.c[2]->w,
    264                                                      weights,mask);break;
    265                     case	4:	sqdist=projectorigin(	cs.c[0]->w,
    266                                                      cs.c[1]->w,
    267                                                      cs.c[2]->w,
    268                                                      cs.c[3]->w,
    269                                                      weights,mask);break;
    270                 }
    271                 if(sqdist>=0)
    272                 {/* Valid	*/
    273                     ns.rank		=	0;
    274                     m_ray		=	btVector3(0,0,0);
    275                     m_current	=	next;
    276                     for(U i=0,ni=cs.rank;i<ni;++i)
    277                     {
    278                         if(mask&(1<<i))
    279                         {
    280                             ns.c[ns.rank]		=	cs.c[i];
    281                             ns.p[ns.rank++]		=	weights[i];
    282                             m_ray				+=	cs.c[i]->w*weights[i];
    283                         }
    284                         else
    285                         {
    286                             m_free[m_nfree++]	=	cs.c[i];
    287                         }
    288                     }
    289                     if(mask==15) m_status=eGjkInside;
    290                 }
    291                 else
    292                 {/* Return old simplex				*/
    293                     removevertice(m_simplices[m_current]);
    294                     break;
    295                 }
    296                 m_status=((++iterations)<GJK_MAX_ITERATIONS)?m_status:eGjkFailed;
    297             } while(m_status==eGjkValid);
    298             m_simplex=&m_simplices[m_current];
    299             switch(m_status)
    300             {
    301                 case	eGjkValid:		m_distance=m_ray.length();break;
    302                 case	eGjkInside:	m_distance=0;break;
    303                 default:
    304                 {
    305                 }
    306             }
    307             return(m_status);
    308         }
    309         bool					EncloseOrigin()
    310         {
    311             switch(m_simplex->rank)
    312             {
    313                 case	1:
    314                 {
    315                     for(U i=0;i<3;++i)
    316                     {
    317                         btVector3		axis=btVector3(0,0,0);
    318                         axis[i]=1;
    319                         appendvertice(*m_simplex, axis);
    320                         if(EncloseOrigin())	return(true);
    321                         removevertice(*m_simplex);
    322                         appendvertice(*m_simplex,-axis);
    323                         if(EncloseOrigin())	return(true);
    324                         removevertice(*m_simplex);
    325                     }
    326                 }
    327                     break;
    328                 case	2:
    329                 {
    330                     const btVector3	d=m_simplex->c[1]->w-m_simplex->c[0]->w;
    331                     for(U i=0;i<3;++i)
    332                     {
    333                         btVector3		axis=btVector3(0,0,0);
    334                         axis[i]=1;
    335                         const btVector3	p=btCross(d,axis);
    336                         if(p.length2()>0)
    337                         {
    338                             appendvertice(*m_simplex, p);
    339                             if(EncloseOrigin())	return(true);
    340                             removevertice(*m_simplex);
    341                             appendvertice(*m_simplex,-p);
    342                             if(EncloseOrigin())	return(true);
    343                             removevertice(*m_simplex);
    344                         }
    345                     }
    346                 }
    347                     break;
    348                 case	3:
    349                 {
    350                     const btVector3	n=btCross(m_simplex->c[1]->w-m_simplex->c[0]->w,
    351                                               m_simplex->c[2]->w-m_simplex->c[0]->w);
    352                     if(n.length2()>0)
    353                     {
    354                         appendvertice(*m_simplex,n);
    355                         if(EncloseOrigin())	return(true);
    356                         removevertice(*m_simplex);
    357                         appendvertice(*m_simplex,-n);
    358                         if(EncloseOrigin())	return(true);
    359                         removevertice(*m_simplex);
    360                     }
    361                 }
    362                     break;
    363                 case	4:
    364                 {
    365                     if(btFabs(det(	m_simplex->c[0]->w-m_simplex->c[3]->w,
    366                                   m_simplex->c[1]->w-m_simplex->c[3]->w,
    367                                   m_simplex->c[2]->w-m_simplex->c[3]->w))>0)
    368                         return(true);
    369                 }
    370                     break;
    371             }
    372             return(false);
    373         }
    374         /* Internals	*/
    375         void				getsupport(const btVector3& d,sSV& sv) const
    376         {
    377             sv.d	=	d/d.length();
    378             sv.w	=	m_shape.Support(sv.d);
    379         }
    380         void				removevertice(sSimplex& simplex)
    381         {
    382             m_free[m_nfree++]=simplex.c[--simplex.rank];
    383         }
    384         void				appendvertice(sSimplex& simplex,const btVector3& v)
    385         {
    386             simplex.p[simplex.rank]=0;
    387             simplex.c[simplex.rank]=m_free[--m_nfree];
    388             getsupport(v,*simplex.c[simplex.rank++]);
    389         }
    390         static btScalar		det(const btVector3& a,const btVector3& b,const btVector3& c)
    391         {
    392             return(	a.y()*b.z()*c.x()+a.z()*b.x()*c.y()-
    393                    a.x()*b.z()*c.y()-a.y()*b.x()*c.z()+
    394                    a.x()*b.y()*c.z()-a.z()*b.y()*c.x());
    395         }
    396         static btScalar		projectorigin(	const btVector3& a,
    397                                           const btVector3& b,
    398                                           btScalar* w,U& m)
    399         {
    400             const btVector3	d=b-a;
    401             const btScalar	l=d.length2();
    402             if(l>GJK_SIMPLEX2_EPS)
    403             {
    404                 const btScalar	t(l>0?-btDot(a,d)/l:0);
    405                 if(t>=1)		{ w[0]=0;w[1]=1;m=2;return(b.length2()); }
    406                 else if(t<=0)	{ w[0]=1;w[1]=0;m=1;return(a.length2()); }
    407                 else			{ w[0]=1-(w[1]=t);m=3;return((a+d*t).length2()); }
    408             }
    409             return(-1);
    410         }
    411         static btScalar		projectorigin(	const btVector3& a,
    412                                           const btVector3& b,
    413                                           const btVector3& c,
    414                                           btScalar* w,U& m)
    415         {
    416             static const U		imd3[]={1,2,0};
    417             const btVector3*	vt[]={&a,&b,&c};
    418             const btVector3		dl[]={a-b,b-c,c-a};
    419             const btVector3		n=btCross(dl[0],dl[1]);
    420             const btScalar		l=n.length2();
    421             if(l>GJK_SIMPLEX3_EPS)
    422             {
    423                 btScalar	mindist=-1;
    424                 btScalar	subw[2]={0.f,0.f};
    425                 U			subm(0);
    426                 for(U i=0;i<3;++i)
    427                 {
    428                     if(btDot(*vt[i],btCross(dl[i],n))>0)
    429                     {
    430                         const U			j=imd3[i];
    431                         const btScalar	subd(projectorigin(*vt[i],*vt[j],subw,subm));
    432                         if((mindist<0)||(subd<mindist))
    433                         {
    434                             mindist		=	subd;
    435                             m			=	static_cast<U>(((subm&1)?1<<i:0)+((subm&2)?1<<j:0));
    436                             w[i]		=	subw[0];
    437                             w[j]		=	subw[1];
    438                             w[imd3[j]]	=	0;
    439                         }
    440                     }
    441                 }
    442                 if(mindist<0)
    443                 {
    444                     const btScalar	d=btDot(a,n);
    445                     const btScalar	s=btSqrt(l);
    446                     const btVector3	p=n*(d/l);
    447                     mindist	=	p.length2();
    448                     m		=	7;
    449                     w[0]	=	(btCross(dl[1],b-p)).length()/s;
    450                     w[1]	=	(btCross(dl[2],c-p)).length()/s;
    451                     w[2]	=	1-(w[0]+w[1]);
    452                 }
    453                 return(mindist);
    454             }
    455             return(-1);
    456         }
    457         static btScalar		projectorigin(	const btVector3& a,
    458                                           const btVector3& b,
    459                                           const btVector3& c,
    460                                           const btVector3& d,
    461                                           btScalar* w,U& m)
    462         {
    463             static const U		imd3[]={1,2,0};
    464             const btVector3*	vt[]={&a,&b,&c,&d};
    465             const btVector3		dl[]={a-d,b-d,c-d};
    466             const btScalar		vl=det(dl[0],dl[1],dl[2]);
    467             const bool			ng=(vl*btDot(a,btCross(b-c,a-b)))<=0;
    468             if(ng&&(btFabs(vl)>GJK_SIMPLEX4_EPS))
    469             {
    470                 btScalar	mindist=-1;
    471                 btScalar	subw[3]={0.f,0.f,0.f};
    472                 U			subm(0);
    473                 for(U i=0;i<3;++i)
    474                 {
    475                     const U			j=imd3[i];
    476                     const btScalar	s=vl*btDot(d,btCross(dl[i],dl[j]));
    477                     if(s>0)
    478                     {
    479                         const btScalar	subd=projectorigin(*vt[i],*vt[j],d,subw,subm);
    480                         if((mindist<0)||(subd<mindist))
    481                         {
    482                             mindist		=	subd;
    483                             m			=	static_cast<U>((subm&1?1<<i:0)+
    484                                                            (subm&2?1<<j:0)+
    485                                                            (subm&4?8:0));
    486                             w[i]		=	subw[0];
    487                             w[j]		=	subw[1];
    488                             w[imd3[j]]	=	0;
    489                             w[3]		=	subw[2];
    490                         }
    491                     }
    492                 }
    493                 if(mindist<0)
    494                 {
    495                     mindist	=	0;
    496                     m		=	15;
    497                     w[0]	=	det(c,b,d)/vl;
    498                     w[1]	=	det(a,c,d)/vl;
    499                     w[2]	=	det(b,a,d)/vl;
    500                     w[3]	=	1-(w[0]+w[1]+w[2]);
    501                 }
    502                 return(mindist);
    503             }
    504             return(-1);
    505         }
    506     };
    507 
    508 
    509 enum	eEpaStatus
    510 {
    511     eEpaValid,
    512     eEpaTouching,
    513     eEpaDegenerated,
    514     eEpaNonConvex,
    515     eEpaInvalidHull,
    516     eEpaOutOfFaces,
    517     eEpaOutOfVertices,
    518     eEpaAccuraryReached,
    519     eEpaFallBack,
    520     eEpaFailed
    521 };
    522 
    523 
    524     // EPA
    525 template <typename btConvexTemplate>
    526     struct	EPA
    527     {
    528         /* Types		*/
    529 
    530         struct	sFace
    531         {
    532             btVector3	n;
    533             btScalar	d;
    534             typename GJK<btConvexTemplate>::sSV*		c[3];
    535             sFace*		f[3];
    536             sFace*		l[2];
    537             U1			e[3];
    538             U1			pass;
    539         };
    540         struct	sList
    541         {
    542             sFace*		root;
    543             U			count;
    544             sList() : root(0),count(0)	{}
    545         };
    546         struct	sHorizon
    547         {
    548             sFace*		cf;
    549             sFace*		ff;
    550             U			nf;
    551             sHorizon() : cf(0),ff(0),nf(0)	{}
    552         };
    553 
    554         /* Fields		*/
    555         eEpaStatus		m_status;
    556         typename GJK<btConvexTemplate>::sSimplex	m_result;
    557         btVector3		m_normal;
    558         btScalar		m_depth;
    559         typename GJK<btConvexTemplate>::sSV				m_sv_store[EPA_MAX_VERTICES];
    560         sFace			m_fc_store[EPA_MAX_FACES];
    561         U				m_nextsv;
    562         sList			m_hull;
    563         sList			m_stock;
    564         /* Methods		*/
    565         EPA()
    566         {
    567             Initialize();
    568         }
    569 
    570 
    571         static inline void		bind(sFace* fa,U ea,sFace* fb,U eb)
    572         {
    573             fa->e[ea]=(U1)eb;fa->f[ea]=fb;
    574             fb->e[eb]=(U1)ea;fb->f[eb]=fa;
    575         }
    576         static inline void		append(sList& list,sFace* face)
    577         {
    578             face->l[0]	=	0;
    579             face->l[1]	=	list.root;
    580             if(list.root) list.root->l[0]=face;
    581             list.root	=	face;
    582             ++list.count;
    583         }
    584         static inline void		remove(sList& list,sFace* face)
    585         {
    586             if(face->l[1]) face->l[1]->l[0]=face->l[0];
    587             if(face->l[0]) face->l[0]->l[1]=face->l[1];
    588             if(face==list.root) list.root=face->l[1];
    589             --list.count;
    590         }
    591 
    592 
    593         void				Initialize()
    594         {
    595             m_status	=	eEpaFailed;
    596             m_normal	=	btVector3(0,0,0);
    597             m_depth		=	0;
    598             m_nextsv	=	0;
    599             for(U i=0;i<EPA_MAX_FACES;++i)
    600             {
    601                 append(m_stock,&m_fc_store[EPA_MAX_FACES-i-1]);
    602             }
    603         }
    604         eEpaStatus			Evaluate(GJK<btConvexTemplate>& gjk,const btVector3& guess)
    605         {
    606             typename GJK<btConvexTemplate>::sSimplex&	simplex=*gjk.m_simplex;
    607             if((simplex.rank>1)&&gjk.EncloseOrigin())
    608             {
    609 
    610                 /* Clean up				*/
    611                 while(m_hull.root)
    612                 {
    613                     sFace*	f = m_hull.root;
    614                     remove(m_hull,f);
    615                     append(m_stock,f);
    616                 }
    617                 m_status	=	eEpaValid;
    618                 m_nextsv	=	0;
    619                 /* Orient simplex		*/
    620                 if(gjk.det(	simplex.c[0]->w-simplex.c[3]->w,
    621                            simplex.c[1]->w-simplex.c[3]->w,
    622                            simplex.c[2]->w-simplex.c[3]->w)<0)
    623                 {
    624                     btSwap(simplex.c[0],simplex.c[1]);
    625                     btSwap(simplex.p[0],simplex.p[1]);
    626                 }
    627                 /* Build initial hull	*/
    628                 sFace*	tetra[]={newface(simplex.c[0],simplex.c[1],simplex.c[2],true),
    629                     newface(simplex.c[1],simplex.c[0],simplex.c[3],true),
    630                     newface(simplex.c[2],simplex.c[1],simplex.c[3],true),
    631                     newface(simplex.c[0],simplex.c[2],simplex.c[3],true)};
    632                 if(m_hull.count==4)
    633                 {
    634                     sFace*		best=findbest();
    635                     sFace		outer=*best;
    636                     U			pass=0;
    637                     U			iterations=0;
    638                     bind(tetra[0],0,tetra[1],0);
    639                     bind(tetra[0],1,tetra[2],0);
    640                     bind(tetra[0],2,tetra[3],0);
    641                     bind(tetra[1],1,tetra[3],2);
    642                     bind(tetra[1],2,tetra[2],1);
    643                     bind(tetra[2],2,tetra[3],1);
    644                     m_status=eEpaValid;
    645                     for(;iterations<EPA_MAX_ITERATIONS;++iterations)
    646                     {
    647                         if(m_nextsv<EPA_MAX_VERTICES)
    648                         {
    649                             sHorizon		horizon;
    650                             typename GJK<btConvexTemplate>::sSV*			w=&m_sv_store[m_nextsv++];
    651                             bool			valid=true;
    652                             best->pass	=	(U1)(++pass);
    653                             gjk.getsupport(best->n,*w);
    654                             const btScalar	wdist=btDot(best->n,w->w)-best->d;
    655                             if(wdist>EPA_ACCURACY)
    656                             {
    657                                 for(U j=0;(j<3)&&valid;++j)
    658                                 {
    659                                     valid&=expand(	pass,w,
    660                                                   best->f[j],best->e[j],
    661                                                   horizon);
    662                                 }
    663                                 if(valid&&(horizon.nf>=3))
    664                                 {
    665                                     bind(horizon.cf,1,horizon.ff,2);
    666                                     remove(m_hull,best);
    667                                     append(m_stock,best);
    668                                     best=findbest();
    669                                     outer=*best;
    670                                 } else { m_status=eEpaInvalidHull;break; }
    671                             } else { m_status=eEpaAccuraryReached;break; }
    672                         } else { m_status=eEpaOutOfVertices;break; }
    673                     }
    674                     const btVector3	projection=outer.n*outer.d;
    675                     m_normal	=	outer.n;
    676                     m_depth		=	outer.d;
    677                     m_result.rank	=	3;
    678                     m_result.c[0]	=	outer.c[0];
    679                     m_result.c[1]	=	outer.c[1];
    680                     m_result.c[2]	=	outer.c[2];
    681                     m_result.p[0]	=	btCross(	outer.c[1]->w-projection,
    682                                                 outer.c[2]->w-projection).length();
    683                     m_result.p[1]	=	btCross(	outer.c[2]->w-projection,
    684                                                 outer.c[0]->w-projection).length();
    685                     m_result.p[2]	=	btCross(	outer.c[0]->w-projection,
    686                                                 outer.c[1]->w-projection).length();
    687                     const btScalar	sum=m_result.p[0]+m_result.p[1]+m_result.p[2];
    688                     m_result.p[0]	/=	sum;
    689                     m_result.p[1]	/=	sum;
    690                     m_result.p[2]	/=	sum;
    691                     return(m_status);
    692                 }
    693             }
    694             /* Fallback		*/
    695             m_status	=	eEpaFallBack;
    696             m_normal	=	-guess;
    697             const btScalar	nl=m_normal.length();
    698             if(nl>0)
    699                 m_normal	=	m_normal/nl;
    700             else
    701                 m_normal	=	btVector3(1,0,0);
    702             m_depth	=	0;
    703             m_result.rank=1;
    704             m_result.c[0]=simplex.c[0];
    705             m_result.p[0]=1;
    706             return(m_status);
    707         }
    708         bool getedgedist(sFace* face, typename GJK<btConvexTemplate>::sSV* a, typename GJK<btConvexTemplate>::sSV* b, btScalar& dist)
    709         {
    710             const btVector3 ba = b->w - a->w;
    711             const btVector3 n_ab = btCross(ba, face->n); // Outward facing edge normal direction, on triangle plane
    712             const btScalar a_dot_nab = btDot(a->w, n_ab); // Only care about the sign to determine inside/outside, so not normalization required
    713 
    714             if(a_dot_nab < 0)
    715             {
    716                 // Outside of edge a->b
    717 
    718                 const btScalar ba_l2 = ba.length2();
    719                 const btScalar a_dot_ba = btDot(a->w, ba);
    720                 const btScalar b_dot_ba = btDot(b->w, ba);
    721 
    722                 if(a_dot_ba > 0)
    723                 {
    724                     // Pick distance vertex a
    725                     dist = a->w.length();
    726                 }
    727                 else if(b_dot_ba < 0)
    728                 {
    729                     // Pick distance vertex b
    730                     dist = b->w.length();
    731                 }
    732                 else
    733                 {
    734                     // Pick distance to edge a->b
    735                     const btScalar a_dot_b = btDot(a->w, b->w);
    736                     dist = btSqrt(btMax((a->w.length2() * b->w.length2() - a_dot_b * a_dot_b) / ba_l2, (btScalar)0));
    737                 }
    738 
    739                 return true;
    740             }
    741 
    742             return false;
    743         }
    744         sFace*				newface(typename GJK<btConvexTemplate>::sSV* a,typename GJK<btConvexTemplate>::sSV* b,typename GJK<btConvexTemplate>::sSV* c,bool forced)
    745         {
    746             if(m_stock.root)
    747             {
    748                 sFace*	face=m_stock.root;
    749                 remove(m_stock,face);
    750                 append(m_hull,face);
    751                 face->pass	=	0;
    752                 face->c[0]	=	a;
    753                 face->c[1]	=	b;
    754                 face->c[2]	=	c;
    755                 face->n		=	btCross(b->w-a->w,c->w-a->w);
    756                 const btScalar	l=face->n.length();
    757                 const bool		v=l>EPA_ACCURACY;
    758 
    759                 if(v)
    760                 {
    761                     if(!(getedgedist(face, a, b, face->d) ||
    762                          getedgedist(face, b, c, face->d) ||
    763                          getedgedist(face, c, a, face->d)))
    764                     {
    765                         // Origin projects to the interior of the triangle
    766                         // Use distance to triangle plane
    767                         face->d = btDot(a->w, face->n) / l;
    768                     }
    769 
    770                     face->n /= l;
    771                     if(forced || (face->d >= -EPA_PLANE_EPS))
    772                     {
    773                         return face;
    774                     }
    775                     else
    776                         m_status=eEpaNonConvex;
    777                 }
    778                 else
    779                     m_status=eEpaDegenerated;
    780 
    781                 remove(m_hull, face);
    782                 append(m_stock, face);
    783                 return 0;
    784 
    785             }
    786             m_status = m_stock.root ? eEpaOutOfVertices : eEpaOutOfFaces;
    787             return 0;
    788         }
    789         sFace*				findbest()
    790         {
    791             sFace*		minf=m_hull.root;
    792             btScalar	mind=minf->d*minf->d;
    793             for(sFace* f=minf->l[1];f;f=f->l[1])
    794             {
    795                 const btScalar	sqd=f->d*f->d;
    796                 if(sqd<mind)
    797                 {
    798                     minf=f;
    799                     mind=sqd;
    800                 }
    801             }
    802             return(minf);
    803         }
    804         bool				expand(U pass,typename GJK<btConvexTemplate>::sSV* w,sFace* f,U e,sHorizon& horizon)
    805         {
    806             static const U	i1m3[]={1,2,0};
    807             static const U	i2m3[]={2,0,1};
    808             if(f->pass!=pass)
    809             {
    810                 const U	e1=i1m3[e];
    811                 if((btDot(f->n,w->w)-f->d)<-EPA_PLANE_EPS)
    812                 {
    813                     sFace*	nf=newface(f->c[e1],f->c[e],w,false);
    814                     if(nf)
    815                     {
    816                         bind(nf,0,f,e);
    817                         if(horizon.cf) bind(horizon.cf,1,nf,2); else horizon.ff=nf;
    818                         horizon.cf=nf;
    819                         ++horizon.nf;
    820                         return(true);
    821                     }
    822                 }
    823                 else
    824                 {
    825                     const U	e2=i2m3[e];
    826                     f->pass		=	(U1)pass;
    827                     if(	expand(pass,w,f->f[e1],f->e[e1],horizon)&&
    828                        expand(pass,w,f->f[e2],f->e[e2],horizon))
    829                     {
    830                         remove(m_hull,f);
    831                         append(m_stock,f);
    832                         return(true);
    833                     }
    834                 }
    835             }
    836             return(false);
    837         }
    838 
    839     };
    840 
    841     template <typename btConvexTemplate>
    842     static void	Initialize(	const btConvexTemplate& a, const btConvexTemplate& b,
    843                            btGjkEpaSolver3::sResults& results,
    844                            MinkowskiDiff<btConvexTemplate>& shape)
    845     {
    846         /* Results		*/
    847         results.witnesses[0]	=
    848         results.witnesses[1]	=	btVector3(0,0,0);
    849         results.status			=	btGjkEpaSolver3::sResults::Separated;
    850         /* Shape		*/
    851 
    852         shape.m_toshape1		=	b.getWorldTransform().getBasis().transposeTimes(a.getWorldTransform().getBasis());
    853         shape.m_toshape0		=	a.getWorldTransform().inverseTimes(b.getWorldTransform());
    854 
    855     }
    856 
    857 
    858 //
    859 // Api
    860 //
    861 
    862 
    863 
    864 //
    865 template <typename btConvexTemplate>
    866 bool		btGjkEpaSolver3_Distance(const btConvexTemplate& a, const btConvexTemplate& b,
    867                                       const btVector3& guess,
    868                                       btGjkEpaSolver3::sResults& results)
    869 {
    870     MinkowskiDiff<btConvexTemplate>			shape(a,b);
    871     Initialize(a,b,results,shape);
    872     GJK<btConvexTemplate>				gjk(a,b);
    873     eGjkStatus	gjk_status=gjk.Evaluate(shape,guess);
    874     if(gjk_status==eGjkValid)
    875     {
    876         btVector3	w0=btVector3(0,0,0);
    877         btVector3	w1=btVector3(0,0,0);
    878         for(U i=0;i<gjk.m_simplex->rank;++i)
    879         {
    880             const btScalar	p=gjk.m_simplex->p[i];
    881             w0+=shape.Support( gjk.m_simplex->c[i]->d,0)*p;
    882             w1+=shape.Support(-gjk.m_simplex->c[i]->d,1)*p;
    883         }
    884         results.witnesses[0]	=	a.getWorldTransform()*w0;
    885         results.witnesses[1]	=	a.getWorldTransform()*w1;
    886         results.normal			=	w0-w1;
    887         results.distance		=	results.normal.length();
    888         results.normal			/=	results.distance>GJK_MIN_DISTANCE?results.distance:1;
    889         return(true);
    890     }
    891     else
    892     {
    893         results.status	=	gjk_status==eGjkInside?
    894         btGjkEpaSolver3::sResults::Penetrating	:
    895         btGjkEpaSolver3::sResults::GJK_Failed	;
    896         return(false);
    897     }
    898 }
    899 
    900 
    901 template <typename btConvexTemplate>
    902 bool	btGjkEpaSolver3_Penetration(const btConvexTemplate& a,
    903                                      const btConvexTemplate& b,
    904                                      const btVector3& guess,
    905                                      btGjkEpaSolver3::sResults& results)
    906 {
    907     MinkowskiDiff<btConvexTemplate>			shape(a,b);
    908     Initialize(a,b,results,shape);
    909     GJK<btConvexTemplate>				gjk(a,b);
    910     eGjkStatus	gjk_status=gjk.Evaluate(shape,-guess);
    911     switch(gjk_status)
    912     {
    913         case	eGjkInside:
    914         {
    915             EPA<btConvexTemplate>				epa;
    916             eEpaStatus	epa_status=epa.Evaluate(gjk,-guess);
    917             if(epa_status!=eEpaFailed)
    918             {
    919                 btVector3	w0=btVector3(0,0,0);
    920                 for(U i=0;i<epa.m_result.rank;++i)
    921                 {
    922                     w0+=shape.Support(epa.m_result.c[i]->d,0)*epa.m_result.p[i];
    923                 }
    924                 results.status			=	btGjkEpaSolver3::sResults::Penetrating;
    925                 results.witnesses[0]	=	a.getWorldTransform()*w0;
    926                 results.witnesses[1]	=	a.getWorldTransform()*(w0-epa.m_normal*epa.m_depth);
    927                 results.normal			=	-epa.m_normal;
    928                 results.distance		=	-epa.m_depth;
    929                 return(true);
    930             } else results.status=btGjkEpaSolver3::sResults::EPA_Failed;
    931         }
    932             break;
    933         case	eGjkFailed:
    934             results.status=btGjkEpaSolver3::sResults::GJK_Failed;
    935             break;
    936         default:
    937         {
    938         }
    939     }
    940     return(false);
    941 }
    942 
    943 #if 0
    944 int	btComputeGjkEpaPenetration2(const btCollisionDescription& colDesc, btDistanceInfo* distInfo)
    945 {
    946     btGjkEpaSolver3::sResults results;
    947     btVector3 guess = colDesc.m_firstDir;
    948 
    949     bool res = btGjkEpaSolver3::Penetration(colDesc.m_objA,colDesc.m_objB,
    950                                             colDesc.m_transformA,colDesc.m_transformB,
    951                                             colDesc.m_localSupportFuncA,colDesc.m_localSupportFuncB,
    952                                             guess,
    953                                             results);
    954     if (res)
    955     {
    956         if ((results.status==btGjkEpaSolver3::sResults::Penetrating) || results.status==GJK::eStatus::Inside)
    957         {
    958             //normal could be 'swapped'
    959 
    960             distInfo->m_distance = results.distance;
    961             distInfo->m_normalBtoA = results.normal;
    962             btVector3 tmpNormalInB = results.witnesses[1]-results.witnesses[0];
    963             btScalar lenSqr = tmpNormalInB.length2();
    964             if (lenSqr <= (SIMD_EPSILON*SIMD_EPSILON))
    965             {
    966                 tmpNormalInB = results.normal;
    967                 lenSqr = results.normal.length2();
    968             }
    969 
    970             if (lenSqr > (SIMD_EPSILON*SIMD_EPSILON))
    971             {
    972                 tmpNormalInB /= btSqrt(lenSqr);
    973                 btScalar distance2 = -(results.witnesses[0]-results.witnesses[1]).length();
    974                 //only replace valid penetrations when the result is deeper (check)
    975                 //if ((distance2 < results.distance))
    976                 {
    977                     distInfo->m_distance = distance2;
    978                     distInfo->m_pointOnA= results.witnesses[0];
    979                     distInfo->m_pointOnB= results.witnesses[1];
    980                     distInfo->m_normalBtoA= tmpNormalInB;
    981                     return 0;
    982                 }
    983             }
    984         }
    985 
    986     }
    987 
    988     return -1;
    989 }
    990 #endif
    991 
    992 template <typename btConvexTemplate, typename btDistanceInfoTemplate>
    993 int	btComputeGjkDistance(const btConvexTemplate& a, const btConvexTemplate& b,
    994                          const btGjkCollisionDescription& colDesc, btDistanceInfoTemplate* distInfo)
    995 {
    996     btGjkEpaSolver3::sResults results;
    997     btVector3 guess = colDesc.m_firstDir;
    998 
    999     bool isSeparated = btGjkEpaSolver3_Distance(	a,b,
   1000                                                  guess,
   1001                                                  results);
   1002     if (isSeparated)
   1003     {
   1004         distInfo->m_distance = results.distance;
   1005         distInfo->m_pointOnA= results.witnesses[0];
   1006         distInfo->m_pointOnB= results.witnesses[1];
   1007         distInfo->m_normalBtoA= results.normal;
   1008         return 0;
   1009     }
   1010 
   1011     return -1;
   1012 }
   1013 
   1014 /* Symbols cleanup		*/
   1015 
   1016 #undef GJK_MAX_ITERATIONS
   1017 #undef GJK_ACCURARY
   1018 #undef GJK_MIN_DISTANCE
   1019 #undef GJK_DUPLICATED_EPS
   1020 #undef GJK_SIMPLEX2_EPS
   1021 #undef GJK_SIMPLEX3_EPS
   1022 #undef GJK_SIMPLEX4_EPS
   1023 
   1024 #undef EPA_MAX_VERTICES
   1025 #undef EPA_MAX_FACES
   1026 #undef EPA_MAX_ITERATIONS
   1027 #undef EPA_ACCURACY
   1028 #undef EPA_FALLBACK
   1029 #undef EPA_PLANE_EPS
   1030 #undef EPA_INSIDE_EPS
   1031 
   1032 
   1033 
   1034 #endif //BT_GJK_EPA3_H
   1035 
   1036