00001 #ifndef GIM_BOX_COLLISION_H_INCLUDED
00002 #define GIM_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
00028
00029
00030
00031
00032
00033
00034
00035 #include "gim_basic_geometry_operations.h"
00036 #include "LinearMath/btTransform.h"
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
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 #define TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,i_dir_0,i_dir_1,i_comp_0,i_comp_1)\
00101 {\
00102 const btScalar dir0 = -edge[i_dir_0];\
00103 const btScalar dir1 = edge[i_dir_1];\
00104 btScalar pmin = pointa[i_comp_0]*dir0 + pointa[i_comp_1]*dir1;\
00105 btScalar pmax = pointb[i_comp_0]*dir0 + pointb[i_comp_1]*dir1;\
00106 if(pmin>pmax)\
00107 {\
00108 GIM_SWAP_NUMBERS(pmin,pmax); \
00109 }\
00110 const btScalar abs_dir0 = absolute_edge[i_dir_0];\
00111 const btScalar abs_dir1 = absolute_edge[i_dir_1];\
00112 const btScalar rad = _extend[i_comp_0] * abs_dir0 + _extend[i_comp_1] * abs_dir1;\
00113 if(pmin>rad || -rad>pmax) return false;\
00114 }\
00115
00116
00117 #define TEST_CROSS_EDGE_BOX_X_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00118 {\
00119 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,2,1,1,2);\
00120 }\
00121
00122 #define TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00123 {\
00124 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,0,2,2,0);\
00125 }\
00126
00127 #define TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(edge,absolute_edge,pointa,pointb,_extend)\
00128 {\
00129 TEST_CROSS_EDGE_BOX_MCR(edge,absolute_edge,pointa,pointb,_extend,1,0,0,1);\
00130 }\
00131
00132
00133
00135 class GIM_BOX_BOX_TRANSFORM_CACHE
00136 {
00137 public:
00138 btVector3 m_T1to0;
00139 btMatrix3x3 m_R1to0;
00140 btMatrix3x3 m_AR;
00141
00142 SIMD_FORCE_INLINE void calc_absolute_matrix()
00143 {
00144 static const btVector3 vepsi(1e-6f,1e-6f,1e-6f);
00145 m_AR[0] = vepsi + m_R1to0[0].absolute();
00146 m_AR[1] = vepsi + m_R1to0[1].absolute();
00147 m_AR[2] = vepsi + m_R1to0[2].absolute();
00148 }
00149
00150 GIM_BOX_BOX_TRANSFORM_CACHE()
00151 {
00152 }
00153
00154
00155 GIM_BOX_BOX_TRANSFORM_CACHE(mat4f trans1_to_0)
00156 {
00157 COPY_MATRIX_3X3(m_R1to0,trans1_to_0)
00158 MAT_GET_TRANSLATION(trans1_to_0,m_T1to0)
00159 calc_absolute_matrix();
00160 }
00161
00163 SIMD_FORCE_INLINE void calc_from_homogenic(const btTransform & trans0,const btTransform & trans1)
00164 {
00165
00166 m_R1to0 = trans0.getBasis().transpose();
00167 m_T1to0 = m_R1to0 * (-trans0.getOrigin());
00168
00169 m_T1to0 += m_R1to0*trans1.getOrigin();
00170 m_R1to0 *= trans1.getBasis();
00171
00172 calc_absolute_matrix();
00173 }
00174
00176 SIMD_FORCE_INLINE void calc_from_full_invert(const btTransform & trans0,const btTransform & trans1)
00177 {
00178 m_R1to0 = trans0.getBasis().inverse();
00179 m_T1to0 = m_R1to0 * (-trans0.getOrigin());
00180
00181 m_T1to0 += m_R1to0*trans1.getOrigin();
00182 m_R1to0 *= trans1.getBasis();
00183
00184 calc_absolute_matrix();
00185 }
00186
00187 SIMD_FORCE_INLINE btVector3 transform(const btVector3 & point)
00188 {
00189 return btVector3(m_R1to0[0].dot(point) + m_T1to0.x(),
00190 m_R1to0[1].dot(point) + m_T1to0.y(),
00191 m_R1to0[2].dot(point) + m_T1to0.z());
00192 }
00193 };
00194
00195
00196 #define BOX_PLANE_EPSILON 0.000001f
00197
00199 class GIM_AABB
00200 {
00201 public:
00202 btVector3 m_min;
00203 btVector3 m_max;
00204
00205 GIM_AABB()
00206 {}
00207
00208
00209 GIM_AABB(const btVector3 & V1,
00210 const btVector3 & V2,
00211 const btVector3 & V3)
00212 {
00213 m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
00214 m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
00215 m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
00216
00217 m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
00218 m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
00219 m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
00220 }
00221
00222 GIM_AABB(const btVector3 & V1,
00223 const btVector3 & V2,
00224 const btVector3 & V3,
00225 GREAL margin)
00226 {
00227 m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
00228 m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
00229 m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
00230
00231 m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
00232 m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
00233 m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
00234
00235 m_min[0] -= margin;
00236 m_min[1] -= margin;
00237 m_min[2] -= margin;
00238 m_max[0] += margin;
00239 m_max[1] += margin;
00240 m_max[2] += margin;
00241 }
00242
00243 GIM_AABB(const GIM_AABB &other):
00244 m_min(other.m_min),m_max(other.m_max)
00245 {
00246 }
00247
00248 GIM_AABB(const GIM_AABB &other,btScalar margin ):
00249 m_min(other.m_min),m_max(other.m_max)
00250 {
00251 m_min[0] -= margin;
00252 m_min[1] -= margin;
00253 m_min[2] -= margin;
00254 m_max[0] += margin;
00255 m_max[1] += margin;
00256 m_max[2] += margin;
00257 }
00258
00259 SIMD_FORCE_INLINE void invalidate()
00260 {
00261 m_min[0] = G_REAL_INFINITY;
00262 m_min[1] = G_REAL_INFINITY;
00263 m_min[2] = G_REAL_INFINITY;
00264 m_max[0] = -G_REAL_INFINITY;
00265 m_max[1] = -G_REAL_INFINITY;
00266 m_max[2] = -G_REAL_INFINITY;
00267 }
00268
00269 SIMD_FORCE_INLINE void increment_margin(btScalar margin)
00270 {
00271 m_min[0] -= margin;
00272 m_min[1] -= margin;
00273 m_min[2] -= margin;
00274 m_max[0] += margin;
00275 m_max[1] += margin;
00276 m_max[2] += margin;
00277 }
00278
00279 SIMD_FORCE_INLINE void copy_with_margin(const GIM_AABB &other, btScalar margin)
00280 {
00281 m_min[0] = other.m_min[0] - margin;
00282 m_min[1] = other.m_min[1] - margin;
00283 m_min[2] = other.m_min[2] - margin;
00284
00285 m_max[0] = other.m_max[0] + margin;
00286 m_max[1] = other.m_max[1] + margin;
00287 m_max[2] = other.m_max[2] + margin;
00288 }
00289
00290 template<typename CLASS_POINT>
00291 SIMD_FORCE_INLINE void calc_from_triangle(
00292 const CLASS_POINT & V1,
00293 const CLASS_POINT & V2,
00294 const CLASS_POINT & V3)
00295 {
00296 m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
00297 m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
00298 m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
00299
00300 m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
00301 m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
00302 m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
00303 }
00304
00305 template<typename CLASS_POINT>
00306 SIMD_FORCE_INLINE void calc_from_triangle_margin(
00307 const CLASS_POINT & V1,
00308 const CLASS_POINT & V2,
00309 const CLASS_POINT & V3, btScalar margin)
00310 {
00311 m_min[0] = GIM_MIN3(V1[0],V2[0],V3[0]);
00312 m_min[1] = GIM_MIN3(V1[1],V2[1],V3[1]);
00313 m_min[2] = GIM_MIN3(V1[2],V2[2],V3[2]);
00314
00315 m_max[0] = GIM_MAX3(V1[0],V2[0],V3[0]);
00316 m_max[1] = GIM_MAX3(V1[1],V2[1],V3[1]);
00317 m_max[2] = GIM_MAX3(V1[2],V2[2],V3[2]);
00318
00319 m_min[0] -= margin;
00320 m_min[1] -= margin;
00321 m_min[2] -= margin;
00322 m_max[0] += margin;
00323 m_max[1] += margin;
00324 m_max[2] += margin;
00325 }
00326
00328 SIMD_FORCE_INLINE void appy_transform(const btTransform & trans)
00329 {
00330 btVector3 center = (m_max+m_min)*0.5f;
00331 btVector3 extends = m_max - center;
00332
00333 center = trans(center);
00334
00335 btVector3 textends(extends.dot(trans.getBasis().getRow(0).absolute()),
00336 extends.dot(trans.getBasis().getRow(1).absolute()),
00337 extends.dot(trans.getBasis().getRow(2).absolute()));
00338
00339 m_min = center - textends;
00340 m_max = center + textends;
00341 }
00342
00344 SIMD_FORCE_INLINE void merge(const GIM_AABB & box)
00345 {
00346 m_min[0] = GIM_MIN(m_min[0],box.m_min[0]);
00347 m_min[1] = GIM_MIN(m_min[1],box.m_min[1]);
00348 m_min[2] = GIM_MIN(m_min[2],box.m_min[2]);
00349
00350 m_max[0] = GIM_MAX(m_max[0],box.m_max[0]);
00351 m_max[1] = GIM_MAX(m_max[1],box.m_max[1]);
00352 m_max[2] = GIM_MAX(m_max[2],box.m_max[2]);
00353 }
00354
00356 template<typename CLASS_POINT>
00357 SIMD_FORCE_INLINE void merge_point(const CLASS_POINT & point)
00358 {
00359 m_min[0] = GIM_MIN(m_min[0],point[0]);
00360 m_min[1] = GIM_MIN(m_min[1],point[1]);
00361 m_min[2] = GIM_MIN(m_min[2],point[2]);
00362
00363 m_max[0] = GIM_MAX(m_max[0],point[0]);
00364 m_max[1] = GIM_MAX(m_max[1],point[1]);
00365 m_max[2] = GIM_MAX(m_max[2],point[2]);
00366 }
00367
00369 SIMD_FORCE_INLINE void get_center_extend(btVector3 & center,btVector3 & extend) const
00370 {
00371 center = (m_max+m_min)*0.5f;
00372 extend = m_max - center;
00373 }
00374
00376 SIMD_FORCE_INLINE void find_intersection(const GIM_AABB & other, GIM_AABB & intersection) const
00377 {
00378 intersection.m_min[0] = GIM_MAX(other.m_min[0],m_min[0]);
00379 intersection.m_min[1] = GIM_MAX(other.m_min[1],m_min[1]);
00380 intersection.m_min[2] = GIM_MAX(other.m_min[2],m_min[2]);
00381
00382 intersection.m_max[0] = GIM_MIN(other.m_max[0],m_max[0]);
00383 intersection.m_max[1] = GIM_MIN(other.m_max[1],m_max[1]);
00384 intersection.m_max[2] = GIM_MIN(other.m_max[2],m_max[2]);
00385 }
00386
00387
00388 SIMD_FORCE_INLINE bool has_collision(const GIM_AABB & other) const
00389 {
00390 if(m_min[0] > other.m_max[0] ||
00391 m_max[0] < other.m_min[0] ||
00392 m_min[1] > other.m_max[1] ||
00393 m_max[1] < other.m_min[1] ||
00394 m_min[2] > other.m_max[2] ||
00395 m_max[2] < other.m_min[2])
00396 {
00397 return false;
00398 }
00399 return true;
00400 }
00401
00407 SIMD_FORCE_INLINE bool collide_ray(const btVector3 & vorigin,const btVector3 & vdir)
00408 {
00409 btVector3 extents,center;
00410 this->get_center_extend(center,extents);;
00411
00412 btScalar Dx = vorigin[0] - center[0];
00413 if(GIM_GREATER(Dx, extents[0]) && Dx*vdir[0]>=0.0f) return false;
00414 btScalar Dy = vorigin[1] - center[1];
00415 if(GIM_GREATER(Dy, extents[1]) && Dy*vdir[1]>=0.0f) return false;
00416 btScalar Dz = vorigin[2] - center[2];
00417 if(GIM_GREATER(Dz, extents[2]) && Dz*vdir[2]>=0.0f) return false;
00418
00419
00420 btScalar f = vdir[1] * Dz - vdir[2] * Dy;
00421 if(btFabs(f) > extents[1]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[1])) return false;
00422 f = vdir[2] * Dx - vdir[0] * Dz;
00423 if(btFabs(f) > extents[0]*btFabs(vdir[2]) + extents[2]*btFabs(vdir[0]))return false;
00424 f = vdir[0] * Dy - vdir[1] * Dx;
00425 if(btFabs(f) > extents[0]*btFabs(vdir[1]) + extents[1]*btFabs(vdir[0]))return false;
00426 return true;
00427 }
00428
00429
00430 SIMD_FORCE_INLINE void projection_interval(const btVector3 & direction, btScalar &vmin, btScalar &vmax) const
00431 {
00432 btVector3 center = (m_max+m_min)*0.5f;
00433 btVector3 extend = m_max-center;
00434
00435 btScalar _fOrigin = direction.dot(center);
00436 btScalar _fMaximumExtent = extend.dot(direction.absolute());
00437 vmin = _fOrigin - _fMaximumExtent;
00438 vmax = _fOrigin + _fMaximumExtent;
00439 }
00440
00441 SIMD_FORCE_INLINE ePLANE_INTERSECTION_TYPE plane_classify(const btVector4 &plane) const
00442 {
00443 btScalar _fmin,_fmax;
00444 this->projection_interval(plane,_fmin,_fmax);
00445
00446 if(plane[3] > _fmax + BOX_PLANE_EPSILON)
00447 {
00448 return G_BACK_PLANE;
00449 }
00450
00451 if(plane[3]+BOX_PLANE_EPSILON >=_fmin)
00452 {
00453 return G_COLLIDE_PLANE;
00454 }
00455 return G_FRONT_PLANE;
00456 }
00457
00458 SIMD_FORCE_INLINE bool overlapping_trans_conservative(const GIM_AABB & box, btTransform & trans1_to_0)
00459 {
00460 GIM_AABB tbox = box;
00461 tbox.appy_transform(trans1_to_0);
00462 return has_collision(tbox);
00463 }
00464
00466 SIMD_FORCE_INLINE bool overlapping_trans_cache(
00467 const GIM_AABB & box,const GIM_BOX_BOX_TRANSFORM_CACHE & transcache, bool fulltest)
00468 {
00469
00470
00471 btVector3 ea,eb;
00472 btVector3 ca,cb;
00473 get_center_extend(ca,ea);
00474 box.get_center_extend(cb,eb);
00475
00476
00477 btVector3 T;
00478 btScalar t,t2;
00479 int i;
00480
00481
00482 for(i=0;i<3;i++)
00483 {
00484 T[i] = transcache.m_R1to0[i].dot(cb) + transcache.m_T1to0[i] - ca[i];
00485 t = transcache.m_AR[i].dot(eb) + ea[i];
00486 if(GIM_GREATER(T[i], t)) return false;
00487 }
00488
00489 for(i=0;i<3;i++)
00490 {
00491 t = MAT_DOT_COL(transcache.m_R1to0,T,i);
00492 t2 = MAT_DOT_COL(transcache.m_AR,ea,i) + eb[i];
00493 if(GIM_GREATER(t,t2)) return false;
00494 }
00495
00496 if(fulltest)
00497 {
00498 int j,m,n,o,p,q,r;
00499 for(i=0;i<3;i++)
00500 {
00501 m = (i+1)%3;
00502 n = (i+2)%3;
00503 o = i==0?1:0;
00504 p = i==2?1:2;
00505 for(j=0;j<3;j++)
00506 {
00507 q = j==2?1:2;
00508 r = j==0?1:0;
00509 t = T[n]*transcache.m_R1to0[m][j] - T[m]*transcache.m_R1to0[n][j];
00510 t2 = ea[o]*transcache.m_AR[p][j] + ea[p]*transcache.m_AR[o][j] +
00511 eb[r]*transcache.m_AR[i][q] + eb[q]*transcache.m_AR[i][r];
00512 if(GIM_GREATER(t,t2)) return false;
00513 }
00514 }
00515 }
00516 return true;
00517 }
00518
00520 SIMD_FORCE_INLINE bool collide_plane(
00521 const btVector4 & plane)
00522 {
00523 ePLANE_INTERSECTION_TYPE classify = plane_classify(plane);
00524 return (classify == G_COLLIDE_PLANE);
00525 }
00526
00528 SIMD_FORCE_INLINE bool collide_triangle_exact(
00529 const btVector3 & p1,
00530 const btVector3 & p2,
00531 const btVector3 & p3,
00532 const btVector4 & triangle_plane)
00533 {
00534 if(!collide_plane(triangle_plane)) return false;
00535
00536 btVector3 center,extends;
00537 this->get_center_extend(center,extends);
00538
00539 const btVector3 v1(p1 - center);
00540 const btVector3 v2(p2 - center);
00541 const btVector3 v3(p3 - center);
00542
00543
00544 btVector3 diff(v2 - v1);
00545 btVector3 abs_diff = diff.absolute();
00546
00547 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00548
00549 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00550
00551 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v1,v3,extends);
00552
00553
00554 diff = v3 - v2;
00555 abs_diff = diff.absolute();
00556
00557 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00558
00559 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00560
00561 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v2,v1,extends);
00562
00563 diff = v1 - v3;
00564 abs_diff = diff.absolute();
00565
00566 TEST_CROSS_EDGE_BOX_X_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00567
00568 TEST_CROSS_EDGE_BOX_Y_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00569
00570 TEST_CROSS_EDGE_BOX_Z_AXIS_MCR(diff,abs_diff,v3,v2,extends);
00571
00572 return true;
00573 }
00574 };
00575
00576
00578 SIMD_FORCE_INLINE bool btCompareTransformsEqual(const btTransform & t1,const btTransform & t2)
00579 {
00580 if(!(t1.getOrigin() == t2.getOrigin()) ) return false;
00581
00582 if(!(t1.getBasis().getRow(0) == t2.getBasis().getRow(0)) ) return false;
00583 if(!(t1.getBasis().getRow(1) == t2.getBasis().getRow(1)) ) return false;
00584 if(!(t1.getBasis().getRow(2) == t2.getBasis().getRow(2)) ) return false;
00585 return true;
00586 }
00587
00588
00589
00590 #endif // GIM_BOX_COLLISION_H_INCLUDED