00001 #ifndef OPENTISSUE_COLLISION_SDF_SDF_COLLISION_POLICY_H
00002 #define OPENTISSUE_COLLISION_SDF_SDF_COLLISION_POLICY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/containers/grid/util/grid_enclosing_indices.h>
00013 #include <OpenTissue/core/containers/grid/util/grid_gradient_at_point.h>
00014 #include <OpenTissue/core/containers/grid/util/grid_value_at_point.h>
00015
00016 namespace OpenTissue
00017 {
00018 namespace sdf
00019 {
00020
00021
00025 template <typename bvh_type_, typename coordsys_type_>
00026 class CollisionPolicy
00027 {
00028 public:
00029
00030 typedef bvh_type_ bvh_type;
00031 typedef coordsys_type_ coordsys_type;
00032
00033 typedef typename bvh_type::bv_ptr bv_ptr;
00034 typedef typename bvh_type::bv_ptr_container bv_ptr_container;
00035 typedef typename bvh_type::bv_iterator bv_iterator;
00036
00037 typedef typename coordsys_type::vector3_type vector3_type;
00038 typedef typename coordsys_type::value_type real_type;
00039
00040
00041 public:
00042
00043 real_type m_envelope;
00044 bool m_flipped;
00045
00046 coordsys_type m_wcs_xform;
00047
00048
00049
00050 public:
00051
00052 CollisionPolicy()
00053 : m_envelope(0.01)
00054 , m_flipped (false)
00055 {}
00056
00057 public:
00058
00069 bool & flipped() { return m_flipped; }
00070 bool const & flipped() const { return m_flipped; }
00071
00072
00073
00082 real_type & envelope() { return m_envelope; }
00083 real_type const & envelope() const { return m_envelope; }
00084
00091 coordsys_type & wcs_xform() { return m_wcs_xform; }
00092 coordsys_type const & wcs_xform() const { return m_wcs_xform; }
00093
00094 public:
00095
00100 template<typename contact_point_container>
00101 void reset(contact_point_container & ) { }
00102
00115 template<typename sdf_geometry_type>
00116 bool overlap(
00117 coordsys_type const & xform
00118 , bv_ptr const & bv
00119 , sdf_geometry_type const & geometry
00120 )
00121 {
00122 typedef typename coordsys_type::vector3_type vector3_type;
00123 typedef typename coordsys_type::value_type real_type;
00124 typedef typename sdf_geometry_type::grid_type grid_type;
00125
00126 grid_type const & phi = geometry.m_phi;
00127
00128 vector3_type center = bv->volume().center();
00129 real_type radius = bv->volume().radius();
00130 xform.xform_point(center);
00131 real_type tst = radius + m_envelope;
00132
00133 if(phi.min_coord() <= center && center <= phi.max_coord())
00134 {
00135
00136
00137 size_t i0,j0,k0,i1,j1,k1;
00138 OpenTissue::grid::enclosing_indices(phi, center, i0, j0, k0, i1, j1, k1);
00139
00140 if(phi(i0,j0,k0) < tst)
00141 return true;
00142 if(phi(i0,j0,k1) < tst)
00143 return true;
00144 if(phi(i0,j1,k0) < tst)
00145 return true;
00146 if(phi(i0,j1,k1) < tst)
00147 return true;
00148 if(phi(i1,j0,k0) < tst)
00149 return true;
00150 if(phi(i1,j0,k1) < tst)
00151 return true;
00152 if(phi(i1,j1,k0) < tst)
00153 return true;
00154 if(phi(i1,j1,k1) < tst)
00155 return true;
00156 return false;
00157 }
00158
00159
00160
00161 vector3_type ext = geometry.ext();
00162 vector3_type proj;
00163 for(unsigned int i =0;i<3;++i)
00164 {
00165 if(ext(i)<center(i))
00166 proj(i) = ext(i);
00167 else if(center(i)<-ext(i))
00168 proj(i) = -ext(i);
00169 else
00170 proj(i) = center(i);
00171 }
00172 real_type sqr_tst = tst*tst;
00173 vector3_type diff = center - proj;
00174 if((diff*diff) < sqr_tst)
00175 return true;
00176 return false;
00177 }
00178
00179
00198 template<typename sdf_geometry_type,typename contact_point_container>
00199 void report(
00200 coordsys_type const & xform
00201 , bv_ptr const & bv
00202 , sdf_geometry_type const & geometry
00203 , contact_point_container & contacts
00204 )
00205 {
00206 using std::min;
00207 typedef typename sdf_geometry_type::grid_type grid_type;
00208 typedef typename contact_point_container::value_type contact_point_type;
00209
00210 grid_type const & phi = geometry.m_phi;
00211
00212 vector3_type center = bv->volume().center();
00213 xform.xform_point(center);
00214
00215 if(phi.min_coord() <= center && center <= phi.max_coord())
00216 {
00217
00218 size_t i0,j0,k0,i1,j1,k1;
00219 OpenTissue::grid::enclosing_indices(phi, center, i0, j0, k0, i1, j1, k1);
00220
00221 real_type d_min = math::detail::highest<real_type>();
00222
00223 real_type d000 = phi(i0,j0,k0);
00224 real_type d001 = phi(i1,j0,k0);
00225 real_type d010 = phi(i0,j1,k0);
00226 real_type d011 = phi(i1,j1,k0);
00227 real_type d100 = phi(i0,j0,k1);
00228 real_type d101 = phi(i1,j0,k1);
00229 real_type d110 = phi(i0,j1,k1);
00230 real_type d111 = phi(i1,j1,k1);
00231
00232 d_min = min(d_min,d000);
00233 d_min = min(d_min,d001);
00234 d_min = min(d_min,d010);
00235 d_min = min(d_min,d011);
00236 d_min = min(d_min,d100);
00237 d_min = min(d_min,d101);
00238 d_min = min(d_min,d110);
00239 d_min = min(d_min,d111);
00240
00241 if(d_min > m_envelope)
00242 return;
00243
00244 real_type s = ( center(0) - ( i0 * phi.dx() + phi.min_coord(0) ) ) / phi.dx();
00245 real_type t = ( center(1) - ( j0 * phi.dy() + phi.min_coord(1) ) ) / phi.dy();
00246 real_type u = ( center(2) - ( k0 * phi.dz() + phi.min_coord(2) ) ) / phi.dz();
00247
00248 real_type x00 = ( 1 - s ) * d000 + s * d001;
00249 real_type x01 = ( 1 - s ) * d010 + s * d011;
00250 real_type x10 = ( 1 - s ) * d100 + s * d101;
00251 real_type x11 = ( 1 - s ) * d110 + s * d111;
00252 real_type y0 = ( 1 - t ) * x00 + t * x01;
00253 real_type y1 = ( 1 - t ) * x10 + t * x11;
00254 real_type distance = ( 1 -u ) * y0 + u * y1;
00255
00256 if(distance>m_envelope)
00257 return;
00258
00259 vector3_type n = OpenTissue::grid::gradient_at_point(phi, center);
00260 if ( n(0) == phi.unused() )
00261 return;
00262
00263
00264
00265
00266 n = -unit(n);
00267
00268
00269
00270
00271 if(m_flipped)
00272 n = - n;
00273
00274
00275
00276
00277
00278 m_wcs_xform.xform_vector( n );
00279 m_wcs_xform.xform_point( center );
00280
00281
00282 contact_point_type cp;
00283 cp.m_n = n;
00284 cp.m_p = center;
00285 cp.m_distance = distance;
00286 contacts.push_back(cp);
00287 }
00288 }
00289
00290 };
00291
00292 }
00293
00294 }
00295
00296
00297 #endif