Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_COLLISION_HANDLERS_MBD_INVERTED_BOX_SPHERE_HANDLER_H
00002 #define OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_COLLISION_HANDLERS_MBD_INVERTED_BOX_SPHERE_HANDLER_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012
00013
00014 namespace OpenTissue
00015 {
00016 namespace mbd
00017 {
00018 namespace collision_detection
00019 {
00020 template<typename mbd_types>
00021 struct InvertedBoxSphereHandler
00022 {
00023 typedef typename mbd_types::math_policy math_policy;
00024
00025 typedef typename math_policy::real_type real_type;
00026 typedef typename math_policy::index_type size_type;
00027 typedef typename math_policy::value_traits value_traits;
00028 typedef typename math_policy::vector3_type vector3_type;
00029 typedef typename math_policy::quaternion_type quaternion_type;
00030 typedef typename math_policy::coordsys_type coordsys_type;
00031
00032 typedef typename mbd_types::body_type body_type;
00033 typedef typename mbd_types::material_type material_type;
00034 typedef typename mbd_types::contact_container contact_container;
00035 typedef typename mbd_types::contact_type contact_type;
00036 typedef typename mbd_types::node_traits node_traits;
00037
00038 typedef OpenTissue::geometry::Sphere<math_policy> sphere_type;
00039 typedef OpenTissue::geometry::OBB<math_policy> box_type;
00040
00041 typedef typename mbd_types::collision_info_type collision_info_type;
00042
00043
00044 static bool test(
00045 sphere_type & sphere
00046 , box_type & box
00047 , collision_info_type & info
00048 )
00049 {
00050 using std::fabs;
00051 using std::sqrt;
00052
00053 coordsys_type BtoWCS;
00054 coordsys_type StoWCS;
00055 vector3_type r_s;
00056 vector3_type r_b;
00057 quaternion_type Q_s;
00058 quaternion_type Q_b;
00059 info.get_body_A()->get_position( r_s );
00060 info.get_body_A()->get_orientation( Q_s );
00061 info.get_body_B()->get_position( r_b );
00062 info.get_body_B()->get_orientation( Q_b );
00063
00064 BtoWCS = coordsys_type( r_b, Q_b );
00065 StoWCS = coordsys_type( r_s, Q_s );
00066
00067
00068 coordsys_type StoB;
00069 StoB = model_update(StoWCS,BtoWCS);
00070 vector3_type c = sphere.center();
00071 StoB.xform_point(c);
00072
00073
00074
00075 real_type r = sphere.radius();
00076 vector3_type a = box.ext();
00077
00078
00079 bool inside = true;
00080 vector3_type n;
00081 vector3_type p = c;
00082 if(c(0)>a(0))
00083 {
00084 p(0) = a(0);
00085 n(0) = value_traits::one();
00086 inside = false;
00087 }
00088 if(c(0)<-a(0))
00089 {
00090 p(0) = -a(0);
00091 n(0) = -value_traits::one();
00092 inside = false;
00093 }
00094 if(c(1)>a(1))
00095 {
00096 p(1) = a(1);
00097 n(1) = value_traits::one();
00098 inside = false;
00099 }
00100 if(c(1)<-a(1))
00101 {
00102 p(1) = -a(1);
00103 n(1) = -value_traits::one();
00104 inside = false;
00105 }
00106 if(c(2)>a(2))
00107 {
00108 p(2) = a(2);
00109 n(2) = value_traits::one();
00110 inside = false;
00111 }
00112 if(c(2)<-a(2))
00113 {
00114 p(2) = -a(2);
00115 n(2) = -value_traits::one();
00116 inside = false;
00117 }
00118
00119
00120
00121
00122 if(inside)
00123 {
00124 info.get_contacts()->clear();
00125
00126
00127
00128
00129
00130
00131
00132
00133
00134 size_type cnt =0;
00135 vector3_type f;
00136 f(0) = a(0) - fabs(c(0));
00137 f(1) = a(1) - fabs(c(1));
00138 f(2) = a(2) - fabs(c(2));
00139
00140 vector3_type dir[3];
00141 dir[0] = vector3_type(value_traits::one(),value_traits::zero(),value_traits::zero());
00142 dir[1] = vector3_type(value_traits::zero(),value_traits::one(),value_traits::zero());
00143 dir[2] = vector3_type(value_traits::zero(),value_traits::zero(),value_traits::one());
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153 size_type permutation[3] = {0,1,2};
00154 for(size_type i=1;i<3;++i)
00155 {
00156 for(size_type j=i;j>0;--j)
00157 {
00158 if(f(permutation[j]) < f(permutation[j-1]))
00159 {
00160 size_type tmp = permutation[j-1];
00161 permutation[j-1] = permutation[j];
00162 permutation[j] = tmp;
00163 }
00164 }
00165 }
00166
00167
00168
00169
00170 int sign[3];
00171 for(size_type i=0;i<3;++i)
00172 sign[i] = boost::numeric_cast<int>( (c(i)<value_traits::zero())?-value_traits::one():value_traits::one() );
00173
00174
00175 size_type case_idx = 0;
00176
00177 for(size_type i=0;i<3;++i)
00178 if(f(i) <= r)
00179 ++case_idx;
00180
00181 vector3_type p[3];
00182 real_type distance[3];
00183 vector3_type n[3];
00184
00185 switch(case_idx)
00186 {
00187 case 0:
00188 return false;
00189 case 1:
00190 {
00191 cnt = 1;
00192 distance[0] = -(r -f(permutation[0]));
00193 n[0] = -sign[permutation[0]]*dir[permutation[0]];
00194 p[0] = c - n[0]*r;
00195 }
00196 break;
00197 case 2:
00198 {
00199 for(size_type i=0;i<2;++i)
00200 {
00201 p[i] = c + sign[permutation[i]]*dir[permutation[i]]*r;
00202 n[i] = -sign[permutation[i]]*dir[permutation[i]];
00203 distance[i] = -(r-f(permutation[i]));
00204 }
00205 cnt = 2;
00206 }
00207 break;
00208 case 3:
00209 {
00210 for(size_type i=0;i<3;++i)
00211 {
00212 p[i] = c + sign[permutation[i]]*dir[permutation[i]]*r;
00213 n[i] = -sign[permutation[i]]*dir[permutation[i]];
00214 distance[i] = -(r-f(permutation[i]));
00215 }
00216 cnt = 3;
00217 }
00218 break;
00219 };
00220
00221 real_type min_distance = value_traits::infinity();
00222 for(size_type i=0;i<cnt;++i)
00223 {
00224 min_distance = (min_distance<distance[i])?min_distance:distance[i];
00225 if(distance[i]<info.get_envelope())
00226 {
00227 contact_type contact;
00228 BtoWCS.xform_vector(n[i]);
00229 BtoWCS.xform_point(p[i]);
00230 contact.init( info.get_body_B(), info.get_body_A(), p[i], n[i], distance[i], info.get_material() );
00231 info.get_contacts()->push_back(contact);
00232 }
00233 }
00234 return (min_distance < -info.get_envelope() );
00235 }
00236 else
00237 {
00238
00239 real_type tmp = sqrt(n*n);
00240 n /= -tmp;
00241 vector3_type diff = c - p;
00242 real_type distance = -(length(diff)+r);
00243 p = p + n*distance;
00244 contact_type contact;
00245 BtoWCS.xform_vector(n);
00246 BtoWCS.xform_point(p);
00247 contact.init( info.get_body_B(), info.get_body_A(), p, n, distance, info.get_material() );
00248 info.get_contacts()->push_back(contact);
00249 return (distance < -info.get_envelope() );
00250 }
00251 return false;
00252 }
00253
00254 static bool mirrowed_test(
00255 box_type & box
00256 , sphere_type & sphere
00257 , collision_info_type & info
00258 )
00259 {
00260 info.flip_bodies();
00261 return test( sphere, box, info);
00262 }
00263
00264
00265 };
00266
00267 }
00268 }
00269 }
00270
00271
00272 #endif