00001 #ifndef OPENTISSUE_COLLISION_AABB_TREE_POLICIES_AABB_TREE_SELF_COLLISION_POLICY_H
00002 #define OPENTISSUE_COLLISION_AABB_TREE_POLICIES_AABB_TREE_SELF_COLLISION_POLICY_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011 #include <OpenTissue/collision/intersect/intersect_aabb_aabb.h>
00012
00013 namespace OpenTissue
00014 {
00015 namespace aabb_tree
00016 {
00017
00018 template<typename aabb_tree_geometry>
00019 class SelfCollisionPolicy
00020 {
00021 public:
00022
00023 typedef typename aabb_tree_geometry::bvh_type bvh_type;
00024 typedef typename bvh_type::volume_type volume_type;
00025 typedef typename bvh_type::geometry_type geometry_type;
00026 typedef typename bvh_type::geometry_iterator geometry_iterator;
00027 typedef typename bvh_type::bv_ptr bv_ptr;
00028 typedef typename bvh_type::annotated_bv_ptr annotated_bv_ptr;
00029 typedef typename bvh_type::annotated_bv_type annotated_bv_type;
00030
00031 typedef typename volume_type::math_types math_types;
00032 typedef typename math_types::real_type real_type;
00033 typedef typename math_types::vector3_type vector3_type;
00034 typedef typename aabb_tree_geometry::vertex_data_type vertex_data_type;
00035
00036 protected:
00037
00038 typedef std::list<std::pair<vertex_data_type*, vertex_data_type*> > edge_container;
00039 typedef std::map<geometry_type *, edge_container > edge_face_lut_type;
00040 edge_face_lut_type m_edge_face_map;
00041
00042 public:
00043
00044 bool curvature_test(bv_ptr ){return false;}
00045 bool curvature_test(bv_ptr,bv_ptr){return false;}
00046 bool adjacent(bv_ptr,bv_ptr){return false;}
00047
00048 bool overlap(bv_ptr A,bv_ptr B) { return OpenTissue::intersect::aabb_aabb(A->volume(),B->volume()); }
00049
00050 template<typename contact_point_container>
00051 void reset(contact_point_container & )
00052 {
00053
00054 m_edge_face_map.clear();
00055 }
00056
00057 template<typename contact_point_container>
00058 void report(
00059 bv_ptr bvA_
00060 , bv_ptr bvB_
00061 , contact_point_container & contacts
00062 )
00063 {
00064 annotated_bv_ptr bvA = boost::static_pointer_cast<annotated_bv_type>(bvA_);
00065 annotated_bv_ptr bvB = boost::static_pointer_cast<annotated_bv_type>(bvB_);
00066
00067 geometry_type * A = &(*(bvA->geometry_begin()));
00068 geometry_type * B = &(*(bvB->geometry_begin()));
00069
00070 if(A==B)
00071 return;
00072 if(is_sharing_node(A,B))
00073 return;
00074 compute_contacts(A,B,contacts);
00075 }
00076
00077 bool is_sharing_node( geometry_type const * A, geometry_type const * B) const
00078 {
00079 if(A->m_p0 == B->m_p0)
00080 return true;
00081 if(A->m_p0 == B->m_p1)
00082 return true;
00083 if(A->m_p0 == B->m_p2)
00084 return true;
00085
00086 if(A->m_p1 == B->m_p0)
00087 return true;
00088 if(A->m_p1 == B->m_p1)
00089 return true;
00090 if(A->m_p1 == B->m_p2)
00091 return true;
00092
00093 if(A->m_p2 == B->m_p0)
00094 return true;
00095 if(A->m_p2 == B->m_p1)
00096 return true;
00097 if(A->m_p2 == B->m_p2)
00098 return true;
00099
00100 return false;
00101 }
00102
00103 template<typename contact_point_container>
00104 bool compute_contacts(
00105 geometry_type * A
00106 , geometry_type * B
00107 , contact_point_container & contacts
00108 )
00109 {
00110 bool collision = false;
00111
00112 collision |= handle_edge_face_intersection( A->m_p0, A->m_p1, B, contacts );
00113 collision |= handle_edge_face_intersection( A->m_p1, A->m_p2, B, contacts );
00114 collision |= handle_edge_face_intersection( A->m_p2, A->m_p0, B, contacts );
00115
00116 collision |= handle_edge_face_intersection( B->m_p0, B->m_p1, A, contacts );
00117 collision |= handle_edge_face_intersection( B->m_p1, B->m_p2, A, contacts );
00118 collision |= handle_edge_face_intersection( B->m_p2, B->m_p0, A, contacts );
00119
00120 return collision;
00121 }
00122
00123 template<typename contact_point_container>
00124 bool handle_edge_face_intersection(
00125 vertex_data_type * origin
00126 , vertex_data_type * destination
00127 , geometry_type * triangle
00128 , contact_point_container & contacts
00129 )
00130 {
00131 typedef typename contact_point_container::value_type contact_point_type;
00132
00133 using std::min;
00134
00135
00136
00137
00138 if(exist_edge_face(origin,destination,triangle))
00139 return false;
00140
00141 vector3_type O = origin->position();
00142 vector3_type D = destination->position();
00143
00144 vector3_type x1 = triangle->m_p0->position();
00145 vector3_type x2 = triangle->m_p1->position();
00146 vector3_type x3 = triangle->m_p2->position();
00147
00148 geometry::Plane<math_types> plane;
00149 plane.set(x1,x2,x3);
00150
00151 real_type dO = plane.signed_distance(O);
00152 real_type dD = plane.signed_distance(D);
00153
00154 if(dO>=0 && dD>=0)
00155 return false;
00156 if(dO<0 && dD<0)
00157 return false;
00158
00159 real_type t;
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169 t = dO/(dO-dD);
00170
00171 vector3_type u;
00172 u = (D-O)*t + O;
00173
00174
00175
00176
00177 real_type w1,w2,w3;
00178 OpenTissue::geometry::barycentric_algebraic(x1,x2,x3,u,w1,w2,w3);
00179
00180
00181
00182
00183 real_type delta = 10e-5;
00184 real_type lower = -delta;
00185 real_type upper = 1.+delta;
00186 if(
00187 (w1>lower)&&(w1<upper)
00188 &&
00189 (w2>lower)&&(w2<upper)
00190 &&
00191 (w3>lower)&&(w3<upper)
00192 )
00193 {
00194
00195 m_edge_face_map[triangle].push_back( std::make_pair(origin,destination) );
00196
00197 contact_point_type cp;
00198
00199 cp.m_distance = min(dO,dD);
00200 cp.m_n = plane.n();
00201 cp.m_p = u;
00202
00203 cp.m_A0 = origin;
00204 cp.m_A1 = destination;
00205 cp.m_A2 = 0;
00206 cp.m_B0 = triangle->m_p0;
00207 cp.m_B1 = triangle->m_p1;
00208 cp.m_B2 = triangle->m_p2;
00209
00210 cp.m_a0 = t;
00211 cp.m_a1 = 0;
00212 cp.m_a2 = 0;
00213 cp.m_b0 = w1;
00214 cp.m_b1 = w2;
00215 cp.m_b2 = w3;
00216
00217 contacts.push_back(cp);
00218
00219 return true;
00220 }
00221 return false;
00222 }
00223
00224 bool exist_edge_face(
00225 vertex_data_type * origin
00226 , vertex_data_type * destination
00227 , geometry_type * triangle
00228 )
00229 {
00230 edge_container * edges = &m_edge_face_map[triangle];
00231
00232 if(edges->empty())
00233 return false;
00234
00235 typename edge_container::iterator edge = edges->begin();
00236 typename edge_container::iterator end = edges->end();
00237
00238 for(;edge!=end;++edge)
00239 {
00240 vertex_data_type * A = edge->first;
00241 vertex_data_type * B = edge->second;
00242 if(
00243 ((A==origin) && (B==destination))
00244 ||
00245 ((B==origin) && (A==destination))
00246 )
00247 return true;
00248 }
00249 return false;
00250 }
00251
00252 };
00253
00254 }
00255 }
00256
00257
00258 #endif