00001 #ifndef BT_BOX_COLLISION_H_INCLUDED
00002 #define BT_BOX_COLLISION_H_INCLUDED
00003
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "LinearMath/btTransform.h"
00028
00029
00031 #define BT_SWAP_NUMBERS(a,b){ \
00032 a = a+b; \
00033 b = a-b; \
00034 a = a-b; \
00035 }\
00036
00037
00038 #define BT_MAX(a,b) (a<b?b:a)
00039 #define BT_MIN(a,b) (a>b?b:a)
00040
00041 #define BT_GREATER(x, y) btFabs(x) > (y)
00042
00043 #define BT_MAX3(a,b,c) BT_MAX(a,BT_MAX(b,c))
00044 #define BT_MIN3(a,b,c) BT_MIN(a,BT_MIN(b,c))
00045
00046
00047
00048
00049
00050
00051 enum eBT_PLANE_INTERSECTION_TYPE
00052 {
00053 BT_CONST_BACK_PLANE = 0,
00054 BT_CONST_COLLIDE_PLANE,
00055 BT_CONST_FRONT_PLANE
00056 };
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119 #define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
00120 {\
00121 const btScalar dir0 = -edge[i_dir_0];\
00122 const btScalar dir1 = edge[i_dir_1];\
00123 btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
00124 btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
00125 if(pmin>pmax)\
00126 {\
00127 BT_SWAP_NUMBERS(pmin,pmax); \
00128 }\
00129 const btScalar abs_dir0 = absolute_edge[i_dir_0];\
00130 const btScalar abs_dir1 = absolute_edge[i_dir_1];\
00131 const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
00132 if(pmin>rad || -rad>pmax) return false;\
00133 }\
00134
00135
00136 #define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00137 {\
00138 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
00139 }\
00140
00141 #define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00142 {\
00143 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
00144 }\
00145
00146 #define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00147 {\
00148 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
00149 }\
00150
00151
00153 SIMD_FORCE_INLINE btScalar bt_mat3_dot_col(
00154 const btMatrix3x3 & mat, const btVector3 & vec3, int colindex)
00155 {
00156 return vec3[0]*mat[0][colindex] + vec3[1]*mat[1][colindex] + vec3[2]*mat[2][colindex];
00157 }
00158
00159
00161 ATTRIBUTE_ALIGNED16 (class) BT_BOX_BOX_TRANSFORM_CACHE
00162 {
00163 public:
00164 btVector3 m_T1to0;
00165 btMatrix3x3 m_R1to0;
00166 btMatrix3x3 m_AR;
00167
00168 SIMD_FORCE_INLINE void calc_absolute_matrix()
00169 {
00170
00171
00172
00173
00174
00175 int i,j;
00176
00177 for(i=0;i<3;i++)
00178 {
00179 for(j=0;j<3;j++ )
00180 {
00181 m_AR[i][j] = 1e-6f + btFabs(m_R1to0[i][j]);
00182 }
00183 }
00184
00185 }
00186
00187 BT_BOX_BOX_TRANSFORM_CACHE()
00188 {
00189 }
00190
00191
00192
00194 SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
00195 {
00196
00197 btTransform temp_trans = trans0.inverse();
00198 temp_trans = temp_trans * trans1;
00199
00200 m_T1to0 = temp_trans.getOrigin();
00201 m_R1to0 = temp_trans.getBasis();
00202
00203
00204 calc_absolute_matrix();
00205 }
00206
00208 SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
00209 {
00210 m_R1to0 = trans0.getBasis().inverse();
00211 m_T1to0 = m_R1to0 * (-trans0.getOrigin());
00212
00213 m_T1to0 += m_R1to0*trans1.getOrigin();
00214 m_R1to0 *= trans1.getBasis();
00215
00216 calc_absolute_matrix();
00217 }
00218
00219 SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point) const
00220 {
00221 return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
00222 m_R1to0[1].dot(point) + m_T1to0.y(),
00223 m_R1to0[2].dot(point) + m_T1to0.z());
00224 }
00225 };
00226
00227
00228 #define BOX_PLANE_EPSILON 0.000001f
00229
00231 ATTRIBUTE_ALIGNED16 (class) btAABB
00232 {
00233 public:
00234 btVector3 m_min;
00235 btVector3 m_max;
00236
00237 btAABB()
00238 {}
00239
00240
00241 btAABB(const btVector3 & V1,
00242 const btVector3 & V2,
00243 const btVector3 & V3)
00244 {
00245 m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
00246 m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
00247 m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
00248
00249 m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
00250 m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
00251 m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
00252 }
00253
00254 btAABB(const btVector3 & V1,
00255 const btVector3 & V2,
00256 const btVector3 & V3,
00257 btScalar margin)
00258 {
00259 m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
00260 m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
00261 m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
00262
00263 m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
00264 m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
00265 m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
00266
00267 m_min[0] -= margin;
00268 m_min[1] -= margin;
00269 m_min[2] -= margin;
00270 m_max[0] += margin;
00271 m_max[1] += margin;
00272 m_max[2] += margin;
00273 }
00274
00275 btAABB(const btAABB &other):
00276 m_min(other.m_min),m_max(other.m_max)
00277 {
00278 }
00279
00280 btAABB(const btAABB &other,btScalar margin ):
00281 m_min(other.m_min),m_max(other.m_max)
00282 {
00283 m_min[0] -= margin;
00284 m_min[1] -= margin;
00285 m_min[2] -= margin;
00286 m_max[0] += margin;
00287 m_max[1] += margin;
00288 m_max[2] += margin;
00289 }
00290
00291 SIMD_FORCE_INLINE void invalidate()
00292 {
00293 m_min[0] = SIMD_INFINITY;
00294 m_min[1] = SIMD_INFINITY;
00295 m_min[2] = SIMD_INFINITY;
00296 m_max[0] = -SIMD_INFINITY;
00297 m_max[1] = -SIMD_INFINITY;
00298 m_max[2] = -SIMD_INFINITY;
00299 }
00300
00301 SIMD_FORCE_INLINE void increment_margin(btScalar margin)
00302 {
00303 m_min[0] -= margin;
00304 m_min[1] -= margin;
00305 m_min[2] -= margin;
00306 m_max[0] += margin;
00307 m_max[1] += margin;
00308 m_max[2] += margin;
00309 }
00310
00311 SIMD_FORCE_INLINE void copy_with_margin(const btAABB &other, btScalar margin)
00312 {
00313 m_min[0] = other.m_min[0] - margin;
00314 m_min[1] = other.m_min[1] - margin;
00315 m_min[2] = other.m_min[2] - margin;
00316
00317 m_max[0] = other.m_max[0] + margin;
00318 m_max[1] = other.m_max[1] + margin;
00319 m_max[2] = other.m_max[2] + margin;
00320 }
00321
00322 template<typename CLASS_POINT>
00323 SIMD_FORCE_INLINE void calc_from_triangle(
00324 const CLASS_POINT & V1,
00325 const CLASS_POINT & V2,
00326 const CLASS_POINT & V3)
00327 {
00328 m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
00329 m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
00330 m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
00331
00332 m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
00333 m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
00334 m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
00335 }
00336
00337 template<typename CLASS_POINT>
00338 SIMD_FORCE_INLINE void calc_from_triangle_margin(
00339 const CLASS_POINT & V1,
00340 const CLASS_POINT & V2,
00341 const CLASS_POINT & V3, btScalar margin)
00342 {
00343 m_min[0] = BT_MIN3(V1[0],V2[0],V3[0]);
00344 m_min[1] = BT_MIN3(V1[1],V2[1],V3[1]);
00345 m_min[2] = BT_MIN3(V1[2],V2[2],V3[2]);
00346
00347 m_max[0] = BT_MAX3(V1[0],V2[0],V3[0]);
00348 m_max[1] = BT_MAX3(V1[1],V2[1],V3[1]);
00349 m_max[2] = BT_MAX3(V1[2],V2[2],V3[2]);
00350
00351 m_min[0] -= margin;
00352 m_min[1] -= margin;
00353 m_min[2] -= margin;
00354 m_max[0] += margin;
00355 m_max[1] += margin;
00356 m_max[2] += margin;
00357 }
00358
00360 SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
00361 {
00362 btVector3 center = (m_max+m_min)*0.5f;
00363 btVector3 extends = m_max - center;
00364
00365 center = trans(center);
00366
00367 btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
00368 extends.dot(trans.getBasis().getRow(1).absolute()),
00369 extends.dot(trans.getBasis().getRow(2).absolute()));
00370
00371 m_min = center - textends;
00372 m_max = center + textends;
00373 }
00374
00375
00377 SIMD_FORCE_INLINE void appy_transform_trans_cache(const BT_BOX_BOX_TRANSFORM_CACHE & trans)
00378 {
00379 btVector3 center = (m_max+m_min)*0.5f;
00380 btVector3 extends = m_max - center;
00381
00382 center = trans.transform(center);
00383
00384 btVector3 textends(extends.dot(trans.m_R1to0.getRow(0).absolute()),
00385 extends.dot(trans.m_R1to0.getRow(1).absolute()),
00386 extends.dot(trans.m_R1to0.getRow(2).absolute()));
00387
00388 m_min = center - textends;
00389 m_max = center + textends;
00390 }
00391
00393 SIMD_FORCE_INLINE void merge(const btAABB & box)
00394 {
00395 m_min[0] = BT_MIN(m_min[0],box.m_min[0]);
00396 m_min[1] = BT_MIN(m_min[1],box.m_min[1]);
00397 m_min[2] = BT_MIN(m_min[2],box.m_min[2]);
00398
00399 m_max[0] = BT_MAX(m_max[0],box.m_max[0]);
00400 m_max[1] = BT_MAX(m_max[1],box.m_max[1]);
00401 m_max[2] = BT_MAX(m_max[2],box.m_max[2]);
00402 }
00403
00405 template<typename CLASS_POINT>
00406 SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
00407 {
00408 m_min[0] = BT_MIN(m_min[0],point[0]);
00409 m_min[1] = BT_MIN(m_min[1],point[1]);
00410 m_min[2] = BT_MIN(m_min[2],point[2]);
00411
00412 m_max[0] = BT_MAX(m_max[0],point[0]);
00413 m_max[1] = BT_MAX(m_max[1],point[1]);
00414 m_max[2] = BT_MAX(m_max[2],point[2]);
00415 }
00416
00418 SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
00419 {
00420 center = (m_max+m_min)*0.5f;
00421 extend = m_max - center;
00422 }
00423
00425 SIMD_FORCE_INLINE void find_intersection(const btAABB & other, btAABB & intersection) const
00426 {
00427 intersection.m_min[0] = BT_MAX(other.m_min[0],m_min[0]);
00428 intersection.m_min[1] = BT_MAX(other.m_min[1],m_min[1]);
00429 intersection.m_min[2] = BT_MAX(other.m_min[2],m_min[2]);
00430
00431 intersection.m_max[0] = BT_MIN(other.m_max[0],m_max[0]);
00432 intersection.m_max[1] = BT_MIN(other.m_max[1],m_max[1]);
00433 intersection.m_max[2] = BT_MIN(other.m_max[2],m_max[2]);
00434 }
00435
00436
00437 SIMD_FORCE_INLINE bool has_collision(const btAABB & other) const
00438 {
00439 if(m_min[0] > other.m_max[0] ||
00440 m_max[0] < other.m_min[0] ||
00441 m_min[1] > other.m_max[1] ||
00442 m_max[1] < other.m_min[1] ||
00443 m_min[2] > other.m_max[2] ||
00444 m_max[2] < other.m_min[2])
00445 {
00446 return false;
00447 }
00448 return true;
00449 }
00450
00456 SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir) const
00457 {
00458 btVector3 extents,center;
00459 this->get_center_extend(center,extents);;
00460
00461 btScalar Dx = vorigin[0] - center[0];
00462 if(BT_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
00463 btScalar Dy = vorigin[1] - center[1];
00464 if(BT_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
00465 btScalar Dz = vorigin[2] - center[2];
00466 if(BT_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
00467
00468
00469 btScalar f = vdir[1] * Dz - vdir[2] * Dy;
00470 if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
00471 f = vdir[2] * Dx - vdir[0] * Dz;
00472 if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
00473 f = vdir[0] * Dy - vdir[1] * Dx;
00474 if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
00475 return true;
00476 }
00477
00478
00479 SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
00480 {
00481 btVector3 center = (m_max+m_min)*0.5f;
00482 btVector3 extend = m_max-center;
00483
00484 btScalar _fOrigin = direction.dot(center);
00485 btScalar _fMaximumExtent = extend.dot(direction.absolute());
00486 vmin = _fOrigin - _fMaximumExtent;
00487 vmax = _fOrigin + _fMaximumExtent;
00488 }
00489
00490 SIMD_FORCE_INLINE eBT_PLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
00491 {
00492 btScalar _fmin,_fmax;
00493 this->projection_interval(plane,_fmin,_fmax);
00494
00495 if(plane[3] > _fmax + BOX_PLANE_EPSILON)
00496 {
00497 return BT_CONST_BACK_PLANE;
00498 }
00499
00500 if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
00501 {
00502 return BT_CONST_COLLIDE_PLANE;
00503 }
00504 return BT_CONST_FRONT_PLANE;
00505 }
00506
00507 SIMD_FORCE_INLINE bool overlapping_trans_conservative(const btAABB & box, btTransform & trans1_to_0) const
00508 {
00509 btAABB tbox = box;
00510 tbox.appy_transform(trans1_to_0);
00511 return has_collision(tbox);
00512 }
00513
00514 SIMD_FORCE_INLINE bool overlapping_trans_conservative2(const btAABB & box,
00515 const BT_BOX_BOX_TRANSFORM_CACHE & trans1_to_0) const
00516 {
00517 btAABB tbox = box;
00518 tbox.appy_transform_trans_cache(trans1_to_0);
00519 return has_collision(tbox);
00520 }
00521
00523 SIMD_FORCE_INLINE bool overlapping_trans_cache(
00524 const btAABB & box,const BT_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest) const
00525 {
00526
00527
00528 btVector3 ea,eb;
00529 btVector3 ca,cb;
00530 get_center_extend(ca,ea);
00531 box.get_center_extend(cb,eb);
00532
00533
00534 btVector3 T;
00535 btScalar t,t2;
00536 int i;
00537
00538
00539 for(i=0;i<3;i++)
00540 {
00541 T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
00542 t = transcache.m_AR[i].dot(eb) + ea[i];
00543 if(BT_GREATER(T[i], t)) return false;
00544 }
00545
00546 for(i=0;i<3;i++)
00547 {
00548 t = bt_mat3_dot_col(transcache.m_R1to0,T,i);
00549 t2 = bt_mat3_dot_col(transcache.m_AR,ea,i) + eb[i];
00550 if(BT_GREATER(t,t2)) return false;
00551 }
00552
00553 if(fulltest)
00554 {
00555 int j,m,n,o,p,q,r;
00556 for(i=0;i<3;i++)
00557 {
00558 m = (i+1)%3;
00559 n = (i+2)%3;
00560 o = i==0?1:0;
00561 p = i==2?1:2;
00562 for(j=0;j<3;j++)
00563 {
00564 q = j==2?1:2;
00565 r = j==0?1:0;
00566 t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
00567 t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
00568 eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
00569 if(BT_GREATER(t,t2)) return false;
00570 }
00571 }
00572 }
00573 return true;
00574 }
00575
00577 SIMD_FORCE_INLINE bool collide_plane(
00578 const btVector4 & plane) const
00579 {
00580 eBT_PLANE_INTERSECTION_TYPE classify = plane_classify(plane);
00581 return (classify == BT_CONST_COLLIDE_PLANE);
00582 }
00583
00585 SIMD_FORCE_INLINE bool collide_triangle_exact(
00586 const btVector3 & p1,
00587 const btVector3 & p2,
00588 const btVector3 & p3,
00589 const btVector4 & triangle_plane) const
00590 {
00591 if(!collide_plane(triangle_plane)) return false;
00592
00593 btVector3 center,extends;
00594 this->get_center_extend(center,extends);
00595
00596 const btVector3 v1(p1 - center);
00597 const btVector3 v2(p2 - center);
00598 const btVector3 v3(p3 - center);
00599
00600
00601 btVector3 diff(v2 - v1);
00602 btVector3 abs_diff = diff.absolute();
00603
00604 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00605
00606 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00607
00608 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00609
00610
00611 diff = v3 - v2;
00612 abs_diff = diff.absolute();
00613
00614 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00615
00616 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00617
00618 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00619
00620 diff = v1 - v3;
00621 abs_diff = diff.absolute();
00622
00623 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00624
00625 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00626
00627 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00628
00629 return true;
00630 }
00631 };
00632
00633
00635 SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
00636 {
00637 if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
00638
00639 if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
00640 if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
00641 if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
00642 return true;
00643 }
00644
00645
00646
00647 #endif // GIM_BOX_COLLISION_H_INCLUDED