Blender V2.61 - r43446
|
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 }