Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_MBD_CACHING_CONTACT_GRAPH_ANALYSIS_H
00002 #define OPENTISSUE_DYNAMICS_MBD_COLLISION_DETECTION_MBD_CACHING_CONTACT_GRAPH_ANALYSIS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/math/math_precision.h>
00013 #include <OpenTissue/core/math/math_constants.h>
00014
00015
00016 namespace OpenTissue
00017 {
00018 namespace mbd
00019 {
00031 template<typename types>
00032 class CachingContactGraphAnalysis
00033 {
00034 protected:
00035
00036 typedef typename types::math_policy::index_type size_type;
00037 typedef typename types::math_policy::vector3_type vector3_type;
00038 typedef typename types::math_policy::matrix3x3_type matrix3x3_type;
00039 typedef typename types::math_policy::quaternion_type quaternion_type;
00040 typedef typename types::math_policy::coordsys_type coordsys_type;
00041
00042 typedef typename types::math_policy::real_type real_type;
00043 typedef typename types::configuration_type configuration_type;
00044 typedef typename types::group_container group_container;
00045 typedef typename types::group_ptr_container group_ptr_container;
00046 typedef typename types::group_type group_type;
00047 typedef typename types::edge_ptr_container edge_ptr_container;
00048 typedef typename types::indirect_edge_iterator indirect_edge_iterator;
00049 typedef typename types::body_type body_type;
00050 typedef typename types::contact_type contact_type;
00051 typedef typename types::edge_type edge_type;
00052 typedef typename types::joint_type joint_type;
00053
00054 public:
00055
00056 class node_traits
00057 {
00058 public:
00059 node_traits()
00060 : m_ccg_absolute_resting(false)
00061 , m_ccg_r_prev(0,0,0)
00062 , m_ccg_Q_prev(0,1,0,0)
00063 {}
00064
00065 public:
00066
00067 vector3_type m_ccg_r_prev;
00068 quaternion_type m_ccg_Q_prev;
00069 bool m_ccg_absolute_resting;
00070
00071
00072
00073
00074 };
00075 class edge_traits
00076 {
00077 public:
00078
00079 typedef enum{
00080 undefined,
00081 separating,
00082 touching,
00083 penetrating
00084 } CCG_StateType;
00085
00086 typedef enum{ white, grey, black } CCG_ColorType;
00087
00088 public:
00089 edge_traits()
00090 : m_ccg_time_stamp(0)
00091 {}
00092 public:
00093 coordsys_type m_ccg_xformAtoB;
00094 coordsys_type m_ccg_xformBtoA;
00095 coordsys_type m_ccg_xformAtoB_prev;
00096 size_type m_ccg_time_stamp;
00097 CCG_StateType m_ccg_state;
00098 CCG_ColorType m_ccg_color;
00099 };
00100 class constraint_traits { };
00101
00102 protected:
00103
00104 configuration_type * m_configuration;
00105 size_type m_time_stamp;
00106
00107 public:
00108
00109 CachingContactGraphAnalysis(void):m_configuration(0),m_time_stamp(0){};
00110
00111 public:
00112
00119 const bool post_broad_phase_analysis( edge_ptr_container & edges )
00120 {
00121 ++m_time_stamp;
00122 assert(m_configuration);
00123 bool penetration = false;
00124 doAbsoluteRestingTest();
00125
00126
00127
00128 indirect_edge_iterator begin(edges.begin());
00129 indirect_edge_iterator end(edges.end());
00130 for( indirect_edge_iterator edge = begin; edge!=end; ++edge )
00131 {
00132 edge->m_ccg_time_stamp = m_time_stamp;
00133 edge->prunned() = true;
00134
00135 if(edge->get_body_A()->has_joint_to(edge->get_body_B()))
00136 continue;
00137 if(edge->get_body_A()->is_fixed() && edge->get_body_B()->is_fixed())
00138 continue;
00139 if(edge->get_body_A()->is_scripted() && edge->get_body_B()->is_scripted())
00140 continue;
00141 if(edge->get_body_A()->is_scripted() && edge->get_body_B()->is_fixed())
00142 continue;
00143 if(edge->get_body_A()->is_fixed() && edge->get_body_B()->is_scripted())
00144 continue;
00145 if(!edge->get_body_A()->is_active() || !edge->get_body_B()->is_active())
00146 continue;
00147 if(edge->get_body_A()->m_ccg_absolute_resting && edge->get_body_B()->m_ccg_absolute_resting )
00148 {
00149 edge->m_relative_resting = true;
00150 continue;
00151 }
00152 vector3_type r_a, r_b;
00153 quaternion_type Q_a, Q_b;
00154 edge->get_body_A()->get_position( r_a );
00155 edge->get_body_A()->get_orientation( Q_a );
00156 edge->get_body_B()->get_position( r_b );
00157 edge->get_body_B()->get_orientation( Q_b );
00158 edge->m_ccg_xformAtoB.setModelUpdate(r_a, Q_a, r_b, Q_b );
00159
00160
00161 real_type epsilon = OpenTissue::math::working_precision<real_type>();
00162 if( edge->m_ccg_xformAtoB.is_equal(edge->m_ccg_xformAtoB_prev,epsilon))
00163 {
00164
00165
00166
00167
00168 edge->m_relative_resting = true;
00169
00170
00171
00172
00173
00174
00175
00176 }
00177 else
00178 {
00179
00180
00181
00182 edge->m_relative_resting = false;
00183 edge->m_ccg_xformAtoB_prev.set(edge->m_ccg_xformAtoB);
00184 edge->m_ccg_xformBtoA.inverse(edge->m_ccg_xformAtoB);
00185 }
00186 edge->prunned() = false;
00187 }
00188 return penetration;
00189 };
00190
00200 void doAbsoluteRestingTest(void)
00201 {
00202
00203 real_type accuracy = 0.001;
00204
00205 for(typename configuration_type::body_iterator body = m_configuration->body_begin();body!=m_configuration->body_end();++body)
00206 {
00207
00208 if(!body->is_active())
00209 continue;
00210
00211 vector3_type r;
00212 quaternion_type Q;
00213 body->get_position( r );
00214 body->get_orientation( Q );
00215 if(
00216 r.is_equal(body->m_ccg_r_prev,accuracy)
00217 &&
00218 Q.is_equal(body->m_ccg_Q_prev,accuracy)
00219 )
00220 {
00221 body->m_ccg_absolute_resting = true;
00222 }
00223 else
00224 {
00225 body->m_ccg_absolute_resting = false;
00226 body->m_ccg_r_prev = r;
00227 body->m_ccg_Q_prev.set(Q);
00228 }
00229 }
00230 };
00231
00243 void post_narrow_phase_analysis(edge_ptr_container & edges )
00244 {
00245 using std::min;
00246
00247 assert(m_configuration);
00248 real_type envelope = m_configuration->get_collision_envelope();
00249 indirect_edge_iterator begin(edges.begin());
00250 indirect_edge_iterator end(edges.end());
00251 for(indirect_edge_iterator edge=begin;edge!=end;++edge)
00252 {
00253 if(edge->prunned())
00254 continue;
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282 edge->m_ccg_state = edge_type::undefined;
00283 real_type minimum = OpenTissue::math::detail::highest<real_type>();
00284 for(typename edge_type::contact_iterator contact = edge->contact_begin();contact != edge->contact_end();++contact)
00285 {
00286 minimum = min(contact->m_distance,minimum);
00287 }
00288 if(minimum > envelope)
00289 {
00290 edge->m_ccg_state = edge_type::separating;
00291 edge->prunned() = true;
00292 continue;
00293 }
00294 if(minimum < -envelope)
00295 edge->m_ccg_state = edge_type::penetrating;
00296 else
00297 edge->m_ccg_state = edge_type::touching;
00298 }
00299 };
00300
00311 void post_contact_determination_analysis( edge_ptr_container & edges, group_ptr_container & reportedGroups )
00312 {
00313 for(typename group_ptr_container::iterator group = reportedGroups.begin();group!=reportedGroups.end();++group)
00314 delete (*group);
00315 reportedGroups.clear();
00316
00317 for(typename configuration_type::body_iterator body = m_configuration->body_begin();body!=m_configuration->body_end();++body)
00318 {
00319 body->m_tag = 0;
00320 }
00321
00322 indirect_edge_iterator begin(edges.begin());
00323 indirect_edge_iterator end(edges.end());
00324 for( indirect_edge_iterator edge = begin; edge!=end; ++edge )
00325 {
00326 assert(edge->m_ccg_time_stamp==m_time_stamp);
00327 edge->m_ccg_color = edge_type::white;
00328 if( edge->m_ccg_state == edge_type::separating)
00329 edge->m_ccg_color = edge_type::black;
00330 if( !edge->get_body_A()->is_active())
00331 edge->m_ccg_color = edge_type::black;
00332 if( !edge->get_body_B()->is_active())
00333 edge->m_ccg_color = edge_type::black;
00334 if( edge->get_body_A()->is_fixed() && edge->get_body_B()->is_fixed())
00335 edge->m_ccg_color = edge_type::black;
00336 if(edge->get_body_A()->is_scripted() && edge->get_body_B()->is_scripted())
00337 edge->m_ccg_color = edge_type::black;
00338 if(edge->get_body_A()->is_scripted() && edge->get_body_B()->is_fixed())
00339 edge->m_ccg_color = edge_type::black;
00340 if(edge->get_body_A()->is_fixed() && edge->get_body_B()->is_scripted())
00341 edge->m_ccg_color = edge_type::black;
00342 if(edge->get_body_A()->has_joint_to(edge->get_body_B()))
00343 edge->m_ccg_color = edge_type::white;
00344 }
00345 int groupTag = 1;
00346 for( indirect_edge_iterator edge = begin; edge!=end; ++edge )
00347 {
00348 if(edge->m_ccg_color == edge_type::white)
00349 {
00350 group_type * group = new group_type();
00351 reportedGroups.push_back(group);
00352 traverseGroup(groupTag,&(*edge),group);
00353 groupTag++;
00354 }
00355 }
00356 group_type * isolated = new group_type();
00357 for(typename configuration_type::body_iterator body = m_configuration->body_begin();body!=m_configuration->body_end();++body)
00358 {
00359 if(body->m_tag==0 && body->is_active() && !body->is_fixed() && !body->is_sleepy() && !body->is_scripted())
00360 isolated->m_bodies.push_back(&(*body));
00361 }
00362 if(isolated->size_bodies()>0)
00363 reportedGroups.push_back(isolated);
00364 else
00365 delete isolated;
00366 };
00367
00368 protected:
00369
00377 void traverseGroup(const size_type groupTag,edge_type * edge,group_type * group)
00378 {
00379 edge->m_ccg_color=edge_type::grey;
00380 if(edge->get_body_A()->m_tag!=groupTag)
00381 {
00382 group->m_bodies.push_back(edge->get_body_A());
00383 edge->get_body_A()->m_tag = groupTag;
00384 }
00385 if(edge->get_body_B()->m_tag!=groupTag)
00386 {
00387 group->m_bodies.push_back(edge->get_body_B());
00388 edge->get_body_B()->m_tag = groupTag;
00389 }
00390
00391 for(typename edge_type::contact_iterator contact = edge->contact_begin();contact!=edge->contact_end();++contact)
00392 {
00393 group->m_contacts.push_back( &(*contact) );
00394 }
00395
00396 if(edge->get_body_A()->has_joint_to(edge->get_body_B()))
00397 {
00398 assert(edge->size_contacts()==0 || !"");
00399
00400 for(typename body_type::indirect_joint_iterator joint = edge->get_body_A()->joint_begin();joint!=edge->get_body_A()->joint_end();++joint)
00401 {
00402 if(joint->get_socket_A()->get_body()==edge->get_body_B() || joint->get_socket_B()->get_body()==edge->get_body_B())
00403 {
00404 group->m_constraints.push_back(&(*joint));
00405 }
00406 }
00407 }
00408 if(!edge->get_body_A()->is_fixed() && !edge->get_body_A()->is_scripted())
00409 {
00410 typename body_type::indirect_edge_iterator begin(edge->get_body_A()->edge_begin());
00411 typename body_type::indirect_edge_iterator end(edge->get_body_A()->edge_end());
00412 for(typename body_type::indirect_edge_iterator neighbor=begin;neighbor!=end;++neighbor)
00413 {
00414 if(neighbor->m_ccg_color == edge_type::white && neighbor->m_ccg_time_stamp==m_time_stamp)
00415 {
00416 traverseGroup(groupTag,&(*neighbor),group);
00417 }
00418 }
00419 }
00420 if(!edge->get_body_B()->is_fixed() && !edge->get_body_A()->is_scripted())
00421 {
00422 typename body_type::indirect_edge_iterator begin(edge->get_body_B()->edge_begin());
00423 typename body_type::indirect_edge_iterator end(edge->get_body_B()->edge_end());
00424 for(typename body_type::indirect_edge_iterator neighbor=begin;neighbor!=end;++neighbor)
00425 {
00426 if(neighbor->m_ccg_color == edge_type::white && neighbor->m_ccg_time_stamp==m_time_stamp)
00427 {
00428 traverseGroup(groupTag,&(*neighbor),group);
00429 }
00430 }
00431 }
00432 edge->m_ccg_color=edge_type::black;
00433 };
00434 public:
00435
00436 void clear()
00437 {
00438 m_time_stamp = 0;
00439 this->m_configuration = 0;
00440 }
00441
00442 void add(body_type * body){}
00443
00444 void remove(body_type * body){}
00445
00446 void init(configuration_type & configuration)
00447 {
00448 clear();
00449 m_configuration = &configuration;
00450 m_time_stamp = 0;
00451 }
00452
00453 };
00454
00455 }
00456 }
00457
00458
00459 #endif