Blender V2.61 - r43446

btBoxBoxDetector.cpp

Go to the documentation of this file.
00001 /*
00002  * Box-Box collision detection re-distributed under the ZLib license with permission from Russell L. Smith
00003  * Original version is from Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.
00004  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org
00005  Bullet Continuous Collision Detection and Physics Library
00006  Bullet is Copyright (c) 2003-2006 Erwin Coumans  http://continuousphysics.com/Bullet/
00007 
00008 This software is provided 'as-is', without any express or implied warranty.
00009 In no event will the authors be held liable for any damages arising from the use of this software.
00010 Permission is granted to anyone to use this software for any purpose, 
00011 including commercial applications, and to alter it and redistribute it freely, 
00012 subject to the following restrictions:
00013 
00014 1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
00015 2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
00016 3. This notice may not be removed or altered from any source distribution.
00017 */
00018 
00020 
00021 #include "btBoxBoxDetector.h"
00022 #include "BulletCollision/CollisionShapes/btBoxShape.h"
00023 
00024 #include <float.h>
00025 #include <string.h>
00026 
00027 btBoxBoxDetector::btBoxBoxDetector(btBoxShape* box1,btBoxShape* box2)
00028 : m_box1(box1),
00029 m_box2(box2)
00030 {
00031 
00032 }
00033 
00034 
00035 // given two boxes (p1,R1,side1) and (p2,R2,side2), collide them together and
00036 // generate contact points. this returns 0 if there is no contact otherwise
00037 // it returns the number of contacts generated.
00038 // `normal' returns the contact normal.
00039 // `depth' returns the maximum penetration depth along that normal.
00040 // `return_code' returns a number indicating the type of contact that was
00041 // detected:
00042 //        1,2,3 = box 2 intersects with a face of box 1
00043 //        4,5,6 = box 1 intersects with a face of box 2
00044 //        7..15 = edge-edge contact
00045 // `maxc' is the maximum number of contacts allowed to be generated, i.e.
00046 // the size of the `contact' array.
00047 // `contact' and `skip' are the contact array information provided to the
00048 // collision functions. this function only fills in the position and depth
00049 // fields.
00050 struct dContactGeom;
00051 #define dDOTpq(a,b,p,q) ((a)[0]*(b)[0] + (a)[p]*(b)[q] + (a)[2*(p)]*(b)[2*(q)])
00052 #define dInfinity FLT_MAX
00053 
00054 
00055 /*PURE_INLINE btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
00056 PURE_INLINE btScalar dDOT13 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,3); }
00057 PURE_INLINE btScalar dDOT31 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,1); }
00058 PURE_INLINE btScalar dDOT33 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,3,3); }
00059 */
00060 static btScalar dDOT   (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,1); }
00061 static btScalar dDOT44 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,4); }
00062 static btScalar dDOT41 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,4,1); }
00063 static btScalar dDOT14 (const btScalar *a, const btScalar *b) { return dDOTpq(a,b,1,4); }
00064 #define dMULTIPLYOP1_331(A,op,B,C) \
00065 {\
00066   (A)[0] op dDOT41((B),(C)); \
00067   (A)[1] op dDOT41((B+1),(C)); \
00068   (A)[2] op dDOT41((B+2),(C)); \
00069 }
00070 
00071 #define dMULTIPLYOP0_331(A,op,B,C) \
00072 { \
00073   (A)[0] op dDOT((B),(C)); \
00074   (A)[1] op dDOT((B+4),(C)); \
00075   (A)[2] op dDOT((B+8),(C)); \
00076 } 
00077 
00078 #define dMULTIPLY1_331(A,B,C) dMULTIPLYOP1_331(A,=,B,C)
00079 #define dMULTIPLY0_331(A,B,C) dMULTIPLYOP0_331(A,=,B,C)
00080 
00081 typedef btScalar dMatrix3[4*3];
00082 
00083 void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
00084                const btVector3& pb, const btVector3& ub,
00085                btScalar *alpha, btScalar *beta);
00086 void dLineClosestApproach (const btVector3& pa, const btVector3& ua,
00087                const btVector3& pb, const btVector3& ub,
00088                btScalar *alpha, btScalar *beta)
00089 {
00090   btVector3 p;
00091   p[0] = pb[0] - pa[0];
00092   p[1] = pb[1] - pa[1];
00093   p[2] = pb[2] - pa[2];
00094   btScalar uaub = dDOT(ua,ub);
00095   btScalar q1 =  dDOT(ua,p);
00096   btScalar q2 = -dDOT(ub,p);
00097   btScalar d = 1-uaub*uaub;
00098   if (d <= btScalar(0.0001f)) {
00099     // @@@ this needs to be made more robust
00100     *alpha = 0;
00101     *beta  = 0;
00102   }
00103   else {
00104     d = 1.f/d;
00105     *alpha = (q1 + uaub*q2)*d;
00106     *beta  = (uaub*q1 + q2)*d;
00107   }
00108 }
00109 
00110 
00111 
00112 // find all the intersection points between the 2D rectangle with vertices
00113 // at (+/-h[0],+/-h[1]) and the 2D quadrilateral with vertices (p[0],p[1]),
00114 // (p[2],p[3]),(p[4],p[5]),(p[6],p[7]).
00115 //
00116 // the intersection points are returned as x,y pairs in the 'ret' array.
00117 // the number of intersection points is returned by the function (this will
00118 // be in the range 0 to 8).
00119 
00120 static int intersectRectQuad2 (btScalar h[2], btScalar p[8], btScalar ret[16])
00121 {
00122   // q (and r) contain nq (and nr) coordinate points for the current (and
00123   // chopped) polygons
00124   int nq=4,nr=0;
00125   btScalar buffer[16];
00126   btScalar *q = p;
00127   btScalar *r = ret;
00128   for (int dir=0; dir <= 1; dir++) {
00129     // direction notation: xy[0] = x axis, xy[1] = y axis
00130     for (int sign=-1; sign <= 1; sign += 2) {
00131       // chop q along the line xy[dir] = sign*h[dir]
00132       btScalar *pq = q;
00133       btScalar *pr = r;
00134       nr = 0;
00135       for (int i=nq; i > 0; i--) {
00136     // go through all points in q and all lines between adjacent points
00137     if (sign*pq[dir] < h[dir]) {
00138       // this point is inside the chopping line
00139       pr[0] = pq[0];
00140       pr[1] = pq[1];
00141       pr += 2;
00142       nr++;
00143       if (nr & 8) {
00144         q = r;
00145         goto done;
00146       }
00147     }
00148     btScalar *nextq = (i > 1) ? pq+2 : q;
00149     if ((sign*pq[dir] < h[dir]) ^ (sign*nextq[dir] < h[dir])) {
00150       // this line crosses the chopping line
00151       pr[1-dir] = pq[1-dir] + (nextq[1-dir]-pq[1-dir]) /
00152         (nextq[dir]-pq[dir]) * (sign*h[dir]-pq[dir]);
00153       pr[dir] = sign*h[dir];
00154       pr += 2;
00155       nr++;
00156       if (nr & 8) {
00157         q = r;
00158         goto done;
00159       }
00160     }
00161     pq += 2;
00162       }
00163       q = r;
00164       r = (q==ret) ? buffer : ret;
00165       nq = nr;
00166     }
00167   }
00168  done:
00169   if (q != ret) memcpy (ret,q,nr*2*sizeof(btScalar));
00170   return nr;
00171 }
00172 
00173 
00174 #define M__PI 3.14159265f
00175 
00176 // given n points in the plane (array p, of size 2*n), generate m points that
00177 // best represent the whole set. the definition of 'best' here is not
00178 // predetermined - the idea is to select points that give good box-box
00179 // collision detection behavior. the chosen point indexes are returned in the
00180 // array iret (of size m). 'i0' is always the first entry in the array.
00181 // n must be in the range [1..8]. m must be in the range [1..n]. i0 must be
00182 // in the range [0..n-1].
00183 
00184 void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[]);
00185 void cullPoints2 (int n, btScalar p[], int m, int i0, int iret[])
00186 {
00187   // compute the centroid of the polygon in cx,cy
00188   int i,j;
00189   btScalar a,cx,cy,q;
00190   if (n==1) {
00191     cx = p[0];
00192     cy = p[1];
00193   }
00194   else if (n==2) {
00195     cx = btScalar(0.5)*(p[0] + p[2]);
00196     cy = btScalar(0.5)*(p[1] + p[3]);
00197   }
00198   else {
00199     a = 0;
00200     cx = 0;
00201     cy = 0;
00202     for (i=0; i<(n-1); i++) {
00203       q = p[i*2]*p[i*2+3] - p[i*2+2]*p[i*2+1];
00204       a += q;
00205       cx += q*(p[i*2]+p[i*2+2]);
00206       cy += q*(p[i*2+1]+p[i*2+3]);
00207     }
00208     q = p[n*2-2]*p[1] - p[0]*p[n*2-1];
00209     if (btFabs(a+q) > SIMD_EPSILON)
00210     {
00211         a = 1.f/(btScalar(3.0)*(a+q));
00212     } else
00213     {
00214         a=BT_LARGE_FLOAT;
00215     }
00216     cx = a*(cx + q*(p[n*2-2]+p[0]));
00217     cy = a*(cy + q*(p[n*2-1]+p[1]));
00218   }
00219 
00220   // compute the angle of each point w.r.t. the centroid
00221   btScalar A[8];
00222   for (i=0; i<n; i++) A[i] = btAtan2(p[i*2+1]-cy,p[i*2]-cx);
00223 
00224   // search for points that have angles closest to A[i0] + i*(2*pi/m).
00225   int avail[8];
00226   for (i=0; i<n; i++) avail[i] = 1;
00227   avail[i0] = 0;
00228   iret[0] = i0;
00229   iret++;
00230   for (j=1; j<m; j++) {
00231     a = btScalar(j)*(2*M__PI/m) + A[i0];
00232     if (a > M__PI) a -= 2*M__PI;
00233     btScalar maxdiff=1e9,diff;
00234 
00235     *iret = i0;         // iret is not allowed to keep this value, but it sometimes does, when diff=#QNAN0
00236 
00237     for (i=0; i<n; i++) {
00238       if (avail[i]) {
00239     diff = btFabs (A[i]-a);
00240     if (diff > M__PI) diff = 2*M__PI - diff;
00241     if (diff < maxdiff) {
00242       maxdiff = diff;
00243       *iret = i;
00244     }
00245       }
00246     }
00247 #if defined(DEBUG) || defined (_DEBUG)
00248     btAssert (*iret != i0); // ensure iret got set
00249 #endif
00250     avail[*iret] = 0;
00251     iret++;
00252   }
00253 }
00254 
00255 
00256 
00257 int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
00258          const btVector3& side1, const btVector3& p2,
00259          const dMatrix3 R2, const btVector3& side2,
00260          btVector3& normal, btScalar *depth, int *return_code,
00261          int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output);
00262 int dBoxBox2 (const btVector3& p1, const dMatrix3 R1,
00263          const btVector3& side1, const btVector3& p2,
00264          const dMatrix3 R2, const btVector3& side2,
00265          btVector3& normal, btScalar *depth, int *return_code,
00266          int maxc, dContactGeom * /*contact*/, int /*skip*/,btDiscreteCollisionDetectorInterface::Result& output)
00267 {
00268   const btScalar fudge_factor = btScalar(1.05);
00269   btVector3 p,pp,normalC(0.f,0.f,0.f);
00270   const btScalar *normalR = 0;
00271   btScalar A[3],B[3],R11,R12,R13,R21,R22,R23,R31,R32,R33,
00272     Q11,Q12,Q13,Q21,Q22,Q23,Q31,Q32,Q33,s,s2,l;
00273   int i,j,invert_normal,code;
00274 
00275   // get vector from centers of box 1 to box 2, relative to box 1
00276   p = p2 - p1;
00277   dMULTIPLY1_331 (pp,R1,p);     // get pp = p relative to body 1
00278 
00279   // get side lengths / 2
00280   A[0] = side1[0]*btScalar(0.5);
00281   A[1] = side1[1]*btScalar(0.5);
00282   A[2] = side1[2]*btScalar(0.5);
00283   B[0] = side2[0]*btScalar(0.5);
00284   B[1] = side2[1]*btScalar(0.5);
00285   B[2] = side2[2]*btScalar(0.5);
00286 
00287   // Rij is R1'*R2, i.e. the relative rotation between R1 and R2
00288   R11 = dDOT44(R1+0,R2+0); R12 = dDOT44(R1+0,R2+1); R13 = dDOT44(R1+0,R2+2);
00289   R21 = dDOT44(R1+1,R2+0); R22 = dDOT44(R1+1,R2+1); R23 = dDOT44(R1+1,R2+2);
00290   R31 = dDOT44(R1+2,R2+0); R32 = dDOT44(R1+2,R2+1); R33 = dDOT44(R1+2,R2+2);
00291 
00292   Q11 = btFabs(R11); Q12 = btFabs(R12); Q13 = btFabs(R13);
00293   Q21 = btFabs(R21); Q22 = btFabs(R22); Q23 = btFabs(R23);
00294   Q31 = btFabs(R31); Q32 = btFabs(R32); Q33 = btFabs(R33);
00295 
00296   // for all 15 possible separating axes:
00297   //   * see if the axis separates the boxes. if so, return 0.
00298   //   * find the depth of the penetration along the separating axis (s2)
00299   //   * if this is the largest depth so far, record it.
00300   // the normal vector will be set to the separating axis with the smallest
00301   // depth. note: normalR is set to point to a column of R1 or R2 if that is
00302   // the smallest depth normal so far. otherwise normalR is 0 and normalC is
00303   // set to a vector relative to body 1. invert_normal is 1 if the sign of
00304   // the normal should be flipped.
00305 
00306 #define TST(expr1,expr2,norm,cc) \
00307   s2 = btFabs(expr1) - (expr2); \
00308   if (s2 > 0) return 0; \
00309   if (s2 > s) { \
00310     s = s2; \
00311     normalR = norm; \
00312     invert_normal = ((expr1) < 0); \
00313     code = (cc); \
00314   }
00315 
00316   s = -dInfinity;
00317   invert_normal = 0;
00318   code = 0;
00319 
00320   // separating axis = u1,u2,u3
00321   TST (pp[0],(A[0] + B[0]*Q11 + B[1]*Q12 + B[2]*Q13),R1+0,1);
00322   TST (pp[1],(A[1] + B[0]*Q21 + B[1]*Q22 + B[2]*Q23),R1+1,2);
00323   TST (pp[2],(A[2] + B[0]*Q31 + B[1]*Q32 + B[2]*Q33),R1+2,3);
00324 
00325   // separating axis = v1,v2,v3
00326   TST (dDOT41(R2+0,p),(A[0]*Q11 + A[1]*Q21 + A[2]*Q31 + B[0]),R2+0,4);
00327   TST (dDOT41(R2+1,p),(A[0]*Q12 + A[1]*Q22 + A[2]*Q32 + B[1]),R2+1,5);
00328   TST (dDOT41(R2+2,p),(A[0]*Q13 + A[1]*Q23 + A[2]*Q33 + B[2]),R2+2,6);
00329 
00330   // note: cross product axes need to be scaled when s is computed.
00331   // normal (n1,n2,n3) is relative to box 1.
00332 #undef TST
00333 #define TST(expr1,expr2,n1,n2,n3,cc) \
00334   s2 = btFabs(expr1) - (expr2); \
00335   if (s2 > SIMD_EPSILON) return 0; \
00336   l = btSqrt((n1)*(n1) + (n2)*(n2) + (n3)*(n3)); \
00337   if (l > SIMD_EPSILON) { \
00338     s2 /= l; \
00339     if (s2*fudge_factor > s) { \
00340       s = s2; \
00341       normalR = 0; \
00342       normalC[0] = (n1)/l; normalC[1] = (n2)/l; normalC[2] = (n3)/l; \
00343       invert_normal = ((expr1) < 0); \
00344       code = (cc); \
00345     } \
00346   }
00347 
00348   btScalar fudge2 (1.0e-5f);
00349 
00350   Q11 += fudge2;
00351   Q12 += fudge2;
00352   Q13 += fudge2;
00353 
00354   Q21 += fudge2;
00355   Q22 += fudge2;
00356   Q23 += fudge2;
00357 
00358   Q31 += fudge2;
00359   Q32 += fudge2;
00360   Q33 += fudge2;
00361 
00362   // separating axis = u1 x (v1,v2,v3)
00363   TST(pp[2]*R21-pp[1]*R31,(A[1]*Q31+A[2]*Q21+B[1]*Q13+B[2]*Q12),0,-R31,R21,7);
00364   TST(pp[2]*R22-pp[1]*R32,(A[1]*Q32+A[2]*Q22+B[0]*Q13+B[2]*Q11),0,-R32,R22,8);
00365   TST(pp[2]*R23-pp[1]*R33,(A[1]*Q33+A[2]*Q23+B[0]*Q12+B[1]*Q11),0,-R33,R23,9);
00366 
00367   // separating axis = u2 x (v1,v2,v3)
00368   TST(pp[0]*R31-pp[2]*R11,(A[0]*Q31+A[2]*Q11+B[1]*Q23+B[2]*Q22),R31,0,-R11,10);
00369   TST(pp[0]*R32-pp[2]*R12,(A[0]*Q32+A[2]*Q12+B[0]*Q23+B[2]*Q21),R32,0,-R12,11);
00370   TST(pp[0]*R33-pp[2]*R13,(A[0]*Q33+A[2]*Q13+B[0]*Q22+B[1]*Q21),R33,0,-R13,12);
00371 
00372   // separating axis = u3 x (v1,v2,v3)
00373   TST(pp[1]*R11-pp[0]*R21,(A[0]*Q21+A[1]*Q11+B[1]*Q33+B[2]*Q32),-R21,R11,0,13);
00374   TST(pp[1]*R12-pp[0]*R22,(A[0]*Q22+A[1]*Q12+B[0]*Q33+B[2]*Q31),-R22,R12,0,14);
00375   TST(pp[1]*R13-pp[0]*R23,(A[0]*Q23+A[1]*Q13+B[0]*Q32+B[1]*Q31),-R23,R13,0,15);
00376 
00377 #undef TST
00378 
00379   if (!code) return 0;
00380 
00381   // if we get to this point, the boxes interpenetrate. compute the normal
00382   // in global coordinates.
00383   if (normalR) {
00384     normal[0] = normalR[0];
00385     normal[1] = normalR[4];
00386     normal[2] = normalR[8];
00387   }
00388   else {
00389     dMULTIPLY0_331 (normal,R1,normalC);
00390   }
00391   if (invert_normal) {
00392     normal[0] = -normal[0];
00393     normal[1] = -normal[1];
00394     normal[2] = -normal[2];
00395   }
00396   *depth = -s;
00397 
00398   // compute contact point(s)
00399 
00400   if (code > 6) {
00401     // an edge from box 1 touches an edge from box 2.
00402     // find a point pa on the intersecting edge of box 1
00403     btVector3 pa;
00404     btScalar sign;
00405     for (i=0; i<3; i++) pa[i] = p1[i];
00406     for (j=0; j<3; j++) {
00407       sign = (dDOT14(normal,R1+j) > 0) ? btScalar(1.0) : btScalar(-1.0);
00408       for (i=0; i<3; i++) pa[i] += sign * A[j] * R1[i*4+j];
00409     }
00410 
00411     // find a point pb on the intersecting edge of box 2
00412     btVector3 pb;
00413     for (i=0; i<3; i++) pb[i] = p2[i];
00414     for (j=0; j<3; j++) {
00415       sign = (dDOT14(normal,R2+j) > 0) ? btScalar(-1.0) : btScalar(1.0);
00416       for (i=0; i<3; i++) pb[i] += sign * B[j] * R2[i*4+j];
00417     }
00418 
00419     btScalar alpha,beta;
00420     btVector3 ua,ub;
00421     for (i=0; i<3; i++) ua[i] = R1[((code)-7)/3 + i*4];
00422     for (i=0; i<3; i++) ub[i] = R2[((code)-7)%3 + i*4];
00423 
00424     dLineClosestApproach (pa,ua,pb,ub,&alpha,&beta);
00425     for (i=0; i<3; i++) pa[i] += ua[i]*alpha;
00426     for (i=0; i<3; i++) pb[i] += ub[i]*beta;
00427 
00428     {
00429         
00430         //contact[0].pos[i] = btScalar(0.5)*(pa[i]+pb[i]);
00431         //contact[0].depth = *depth;
00432         btVector3 pointInWorld;
00433 
00434 #ifdef USE_CENTER_POINT
00435         for (i=0; i<3; i++) 
00436             pointInWorld[i] = (pa[i]+pb[i])*btScalar(0.5);
00437         output.addContactPoint(-normal,pointInWorld,-*depth);
00438 #else
00439         output.addContactPoint(-normal,pb,-*depth);
00440 
00441 #endif //
00442         *return_code = code;
00443     }
00444     return 1;
00445   }
00446 
00447   // okay, we have a face-something intersection (because the separating
00448   // axis is perpendicular to a face). define face 'a' to be the reference
00449   // face (i.e. the normal vector is perpendicular to this) and face 'b' to be
00450   // the incident face (the closest face of the other box).
00451 
00452   const btScalar *Ra,*Rb,*pa,*pb,*Sa,*Sb;
00453   if (code <= 3) {
00454     Ra = R1;
00455     Rb = R2;
00456     pa = p1;
00457     pb = p2;
00458     Sa = A;
00459     Sb = B;
00460   }
00461   else {
00462     Ra = R2;
00463     Rb = R1;
00464     pa = p2;
00465     pb = p1;
00466     Sa = B;
00467     Sb = A;
00468   }
00469 
00470   // nr = normal vector of reference face dotted with axes of incident box.
00471   // anr = absolute values of nr.
00472   btVector3 normal2,nr,anr;
00473   if (code <= 3) {
00474     normal2[0] = normal[0];
00475     normal2[1] = normal[1];
00476     normal2[2] = normal[2];
00477   }
00478   else {
00479     normal2[0] = -normal[0];
00480     normal2[1] = -normal[1];
00481     normal2[2] = -normal[2];
00482   }
00483   dMULTIPLY1_331 (nr,Rb,normal2);
00484   anr[0] = btFabs (nr[0]);
00485   anr[1] = btFabs (nr[1]);
00486   anr[2] = btFabs (nr[2]);
00487 
00488   // find the largest compontent of anr: this corresponds to the normal
00489   // for the indident face. the other axis numbers of the indicent face
00490   // are stored in a1,a2.
00491   int lanr,a1,a2;
00492   if (anr[1] > anr[0]) {
00493     if (anr[1] > anr[2]) {
00494       a1 = 0;
00495       lanr = 1;
00496       a2 = 2;
00497     }
00498     else {
00499       a1 = 0;
00500       a2 = 1;
00501       lanr = 2;
00502     }
00503   }
00504   else {
00505     if (anr[0] > anr[2]) {
00506       lanr = 0;
00507       a1 = 1;
00508       a2 = 2;
00509     }
00510     else {
00511       a1 = 0;
00512       a2 = 1;
00513       lanr = 2;
00514     }
00515   }
00516 
00517   // compute center point of incident face, in reference-face coordinates
00518   btVector3 center;
00519   if (nr[lanr] < 0) {
00520     for (i=0; i<3; i++) center[i] = pb[i] - pa[i] + Sb[lanr] * Rb[i*4+lanr];
00521   }
00522   else {
00523     for (i=0; i<3; i++) center[i] = pb[i] - pa[i] - Sb[lanr] * Rb[i*4+lanr];
00524   }
00525 
00526   // find the normal and non-normal axis numbers of the reference box
00527   int codeN,code1,code2;
00528   if (code <= 3) codeN = code-1; else codeN = code-4;
00529   if (codeN==0) {
00530     code1 = 1;
00531     code2 = 2;
00532   }
00533   else if (codeN==1) {
00534     code1 = 0;
00535     code2 = 2;
00536   }
00537   else {
00538     code1 = 0;
00539     code2 = 1;
00540   }
00541 
00542   // find the four corners of the incident face, in reference-face coordinates
00543   btScalar quad[8]; // 2D coordinate of incident face (x,y pairs)
00544   btScalar c1,c2,m11,m12,m21,m22;
00545   c1 = dDOT14 (center,Ra+code1);
00546   c2 = dDOT14 (center,Ra+code2);
00547   // optimize this? - we have already computed this data above, but it is not
00548   // stored in an easy-to-index format. for now it's quicker just to recompute
00549   // the four dot products.
00550   m11 = dDOT44 (Ra+code1,Rb+a1);
00551   m12 = dDOT44 (Ra+code1,Rb+a2);
00552   m21 = dDOT44 (Ra+code2,Rb+a1);
00553   m22 = dDOT44 (Ra+code2,Rb+a2);
00554   {
00555     btScalar k1 = m11*Sb[a1];
00556     btScalar k2 = m21*Sb[a1];
00557     btScalar k3 = m12*Sb[a2];
00558     btScalar k4 = m22*Sb[a2];
00559     quad[0] = c1 - k1 - k3;
00560     quad[1] = c2 - k2 - k4;
00561     quad[2] = c1 - k1 + k3;
00562     quad[3] = c2 - k2 + k4;
00563     quad[4] = c1 + k1 + k3;
00564     quad[5] = c2 + k2 + k4;
00565     quad[6] = c1 + k1 - k3;
00566     quad[7] = c2 + k2 - k4;
00567   }
00568 
00569   // find the size of the reference face
00570   btScalar rect[2];
00571   rect[0] = Sa[code1];
00572   rect[1] = Sa[code2];
00573 
00574   // intersect the incident and reference faces
00575   btScalar ret[16];
00576   int n = intersectRectQuad2 (rect,quad,ret);
00577   if (n < 1) return 0;      // this should never happen
00578 
00579   // convert the intersection points into reference-face coordinates,
00580   // and compute the contact position and depth for each point. only keep
00581   // those points that have a positive (penetrating) depth. delete points in
00582   // the 'ret' array as necessary so that 'point' and 'ret' correspond.
00583   btScalar point[3*8];      // penetrating contact points
00584   btScalar dep[8];          // depths for those points
00585   btScalar det1 = 1.f/(m11*m22 - m12*m21);
00586   m11 *= det1;
00587   m12 *= det1;
00588   m21 *= det1;
00589   m22 *= det1;
00590   int cnum = 0;         // number of penetrating contact points found
00591   for (j=0; j < n; j++) {
00592     btScalar k1 =  m22*(ret[j*2]-c1) - m12*(ret[j*2+1]-c2);
00593     btScalar k2 = -m21*(ret[j*2]-c1) + m11*(ret[j*2+1]-c2);
00594     for (i=0; i<3; i++) point[cnum*3+i] =
00595               center[i] + k1*Rb[i*4+a1] + k2*Rb[i*4+a2];
00596     dep[cnum] = Sa[codeN] - dDOT(normal2,point+cnum*3);
00597     if (dep[cnum] >= 0) {
00598       ret[cnum*2] = ret[j*2];
00599       ret[cnum*2+1] = ret[j*2+1];
00600       cnum++;
00601     }
00602   }
00603   if (cnum < 1) return 0;   // this should never happen
00604 
00605   // we can't generate more contacts than we actually have
00606   if (maxc > cnum) maxc = cnum;
00607   if (maxc < 1) maxc = 1;
00608 
00609   if (cnum <= maxc) {
00610 
00611       if (code<4) 
00612       {
00613     // we have less contacts than we need, so we use them all
00614     for (j=0; j < cnum; j++) 
00615     {
00616         btVector3 pointInWorld;
00617         for (i=0; i<3; i++) 
00618             pointInWorld[i] = point[j*3+i] + pa[i];
00619         output.addContactPoint(-normal,pointInWorld,-dep[j]);
00620 
00621     }
00622       } else
00623       {
00624           // we have less contacts than we need, so we use them all
00625         for (j=0; j < cnum; j++) 
00626         {
00627             btVector3 pointInWorld;
00628             for (i=0; i<3; i++) 
00629                 pointInWorld[i] = point[j*3+i] + pa[i]-normal[i]*dep[j];
00630                 //pointInWorld[i] = point[j*3+i] + pa[i];
00631             output.addContactPoint(-normal,pointInWorld,-dep[j]);
00632         }
00633       }
00634   }
00635   else {
00636     // we have more contacts than are wanted, some of them must be culled.
00637     // find the deepest point, it is always the first contact.
00638     int i1 = 0;
00639     btScalar maxdepth = dep[0];
00640     for (i=1; i<cnum; i++) {
00641       if (dep[i] > maxdepth) {
00642     maxdepth = dep[i];
00643     i1 = i;
00644       }
00645     }
00646 
00647     int iret[8];
00648     cullPoints2 (cnum,ret,maxc,i1,iret);
00649 
00650     for (j=0; j < maxc; j++) {
00651 //      dContactGeom *con = CONTACT(contact,skip*j);
00652   //    for (i=0; i<3; i++) con->pos[i] = point[iret[j]*3+i] + pa[i];
00653     //  con->depth = dep[iret[j]];
00654 
00655         btVector3 posInWorld;
00656         for (i=0; i<3; i++) 
00657             posInWorld[i] = point[iret[j]*3+i] + pa[i];
00658         if (code<4) 
00659        {
00660             output.addContactPoint(-normal,posInWorld,-dep[iret[j]]);
00661         } else
00662         {
00663             output.addContactPoint(-normal,posInWorld-normal*dep[iret[j]],-dep[iret[j]]);
00664         }
00665     }
00666     cnum = maxc;
00667   }
00668 
00669   *return_code = code;
00670   return cnum;
00671 }
00672 
00673 void    btBoxBoxDetector::getClosestPoints(const ClosestPointInput& input,Result& output,class btIDebugDraw* /*debugDraw*/,bool /*swapResults*/)
00674 {
00675     
00676     const btTransform& transformA = input.m_transformA;
00677     const btTransform& transformB = input.m_transformB;
00678     
00679     int skip = 0;
00680     dContactGeom *contact = 0;
00681 
00682     dMatrix3 R1;
00683     dMatrix3 R2;
00684 
00685     for (int j=0;j<3;j++)
00686     {
00687         R1[0+4*j] = transformA.getBasis()[j].x();
00688         R2[0+4*j] = transformB.getBasis()[j].x();
00689 
00690         R1[1+4*j] = transformA.getBasis()[j].y();
00691         R2[1+4*j] = transformB.getBasis()[j].y();
00692 
00693 
00694         R1[2+4*j] = transformA.getBasis()[j].z();
00695         R2[2+4*j] = transformB.getBasis()[j].z();
00696 
00697     }
00698 
00699     
00700 
00701     btVector3 normal;
00702     btScalar depth;
00703     int return_code;
00704     int maxc = 4;
00705 
00706 
00707     dBoxBox2 (transformA.getOrigin(), 
00708     R1,
00709     2.f*m_box1->getHalfExtentsWithMargin(),
00710     transformB.getOrigin(),
00711     R2, 
00712     2.f*m_box2->getHalfExtentsWithMargin(),
00713     normal, &depth, &return_code,
00714     maxc, contact, skip,
00715     output
00716     );
00717 
00718 }