Go to the documentation of this file.00001 #ifndef OPENTISSUE_DYNAMICS_VERSATILE_VERSATILE_SIMULATOR_H
00002 #define OPENTISSUE_DYNAMICS_VERSATILE_VERSATILE_SIMULATOR_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/dynamics/versatile/versatile_mesh.h>
00013 #include <OpenTissue/dynamics/versatile/versatile_collision_policy.h>
00014 #include <OpenTissue/collision/spatial_hashing/spatial_hashing.h>
00015 #include <OpenTissue/core/geometry/geometry_plane.h>
00016
00017 #include <boost/iterator/indirect_iterator.hpp>
00018
00019 #include <list>
00020
00021 namespace OpenTissue
00022 {
00023 namespace versatile
00024 {
00025
00034 template< typename versatile_types >
00035 class Simulator
00036 {
00037 public:
00038
00039 typedef typename versatile_types::value_traits value_traits;
00040 typedef typename versatile_types::real_type real_type;
00041 typedef typename versatile_types::vector3_type vector3_type;
00042 typedef typename versatile_types::matrix3x3_type matrix3x3_type;
00043
00044 typedef OpenTissue::versatile::Mesh<versatile_types> mesh_type;
00045 typedef typename std::list<mesh_type*> mesh_ptr_container;
00046 typedef typename mesh_ptr_container::iterator mesh_ptr_iterator;
00047 typedef boost::indirect_iterator<mesh_ptr_iterator,mesh_type> mesh_iterator;
00048
00049 typedef OpenTissue::versatile::detail::collision_policy<versatile_types> policy;
00050
00051 typedef OpenTissue::spatial_hashing::PointDataQuery<typename policy::hash_grid,policy> point_query_type;
00052
00053 typedef typename policy::result_container contact_container;
00054 typedef typename contact_container::iterator contact_iterator;
00055 typedef OpenTissue::geometry::Plane<versatile_types> plane_type;
00056
00057
00058 protected:
00059
00060 mesh_ptr_container m_meshes;
00061 contact_container m_contacts;
00062 point_query_type m_point_query;
00063
00064 public:
00065
00066 void add(mesh_type & mesh)
00067 {
00068 m_point_query.auto_init_settings(mesh.tetrahedron_begin(),mesh.tetrahedron_end());
00069 m_meshes.push_back(&mesh);
00070 }
00071
00072 void clear() { m_meshes.clear(); }
00073
00083 void run(real_type const & dT,real_type const & fraction)
00084 {
00085 using std::min;
00086 using std::ceil;
00087 using std::log;
00088
00089 assert(dT>value_traits::zero() || !"run(): Frame time-step must be positive");
00090 assert( (fraction>value_traits::zero() && fraction<=value_traits::one() ) || !"run(): penetration reduction parameter must be wihtin (0..1]");
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103 real_type const min_dt = boost::numeric_cast<real_type>( 0.001 );
00104
00105 real_type n = ceil( - log( fraction ));
00106 real_type tau = dT/n;
00107 real_type mu = value_traits::one();
00108 real_type b = (value_traits::two()*mu)/tau;
00109 real_type dt = min(min_dt,value_traits::four()*mu/b);
00110 int N = boost::numeric_cast<int>( ceil(dT/dt) );
00111
00112 collision_detection();
00113
00114 for(int i=0;i<N;++i)
00115 run(dT,fraction,dt);
00116 }
00117
00118 real_type compute_internal_energy()
00119 {
00120 real_type energy = value_traits::zero();
00121 mesh_iterator begin = m_meshes.begin();
00122 mesh_iterator end = m_meshes.end();
00123 mesh_iterator mesh;
00124 for(mesh=begin;mesh!=end;++mesh)
00125 energy += mesh->compute_internal_energy();
00126 return energy;
00127 }
00128
00129
00130 protected:
00131
00142 void run(real_type const & dT,real_type const & fraction,real_type const & dt)
00143 {
00144 assert(dT>value_traits::zero() || !"run(): Frame time-step must be positive");
00145 assert( ( fraction>value_traits::zero() && fraction<=value_traits::one() ) || !"run(): penetration reduction parameter must be wihtin (0..1]");
00146 assert(dt>value_traits::zero() || !"run(): simulation time-step must be positive");
00147 assert(dt<dT || !"run(): simulation time-step must be smaller than frame time-step");
00148
00149 mesh_iterator begin = m_meshes.begin();
00150 mesh_iterator end = m_meshes.end();
00151 mesh_iterator mesh;
00152
00153 for(mesh=begin;mesh!=end;++mesh)
00154 mesh->clear_constraint_forces();
00155
00156 collision_resolving(dT,fraction);
00157
00158 for(mesh=begin;mesh!=end;++mesh)
00159 mesh->apply_constraint_forces();
00160
00161 for(mesh=begin;mesh!=end;++mesh)
00162 mesh->integrate(dt);
00163 }
00164
00165 void collision_resolving(real_type const & dT,real_type const & fraction)
00166 {
00167 using std::ceil;
00168 using std::log;
00169
00170 plane_type plane[4];
00171 real_type d[4];
00172
00173 assert(dT>value_traits::zero() || !"collision_resolving(): Frame time-step must be positive");
00174 assert( ( fraction>value_traits::zero() && fraction<=value_traits::one() ) || !"collision_resolving(): penetration reduction parameter must be wihtin (0..1]");
00175
00176 real_type n = ceil( - log( fraction ));
00177 real_type tau = dT/n;
00178 {
00179 mesh_iterator begin = m_meshes.begin();
00180 mesh_iterator end = m_meshes.end();
00181 mesh_iterator mesh;
00182 for(mesh=begin;mesh!=end;++mesh)
00183 mesh->clear_penalty_forces();
00184 }
00185 contact_iterator begin = m_contacts.begin();
00186 contact_iterator end = m_contacts.end();
00187 contact_iterator contact;
00188 for(contact=begin;contact!=end;++contact)
00189 {
00190 vector3_type & ni = contact->m_query->i()->m_coord;
00191 vector3_type & nj = contact->m_query->j()->m_coord;
00192 vector3_type & nk = contact->m_query->k()->m_coord;
00193 vector3_type & nm = contact->m_query->m()->m_coord;
00194 vector3_type & p = contact->m_data->m_coord;
00195 vector3_type & v = contact->m_data->m_v;
00196 plane[0].set(nk,nj,ni);
00197 plane[1].set(ni,nj,nm);
00198 plane[2].set(nj,nk,nm);
00199 plane[3].set(nk,ni,nm);
00200 for(unsigned int i=0;i<4;++i)
00201 d[i] = plane[i].signed_distance(p);
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211 real_type max_d = d[0];
00212 int max_i = 0;
00213 for(int i=1;i<4;++i)
00214 if (d[i]>max_d)
00215 {
00216 max_d = d[i];
00217 max_i = i;
00218 }
00219
00220 if( max_d>value_traits::zero() )
00221 continue;
00222
00223 real_type mu = contact->m_data->m_mass;
00224 real_type b = (value_traits::two()*mu)/tau;
00225 real_type k = mu/(tau*tau);
00226
00227 vector3_type & n = plane[max_i].n();
00228 vector3_type & f = contact->m_data->m_f_pen;
00229
00230 f += k*n*max_d - b*(v*n)*n;
00231 }
00232 }
00233 void collision_detection()
00234 {
00235 mesh_iterator begin = m_meshes.begin();
00236 mesh_iterator end = m_meshes.end();
00237 mesh_iterator mesh;
00238 m_contacts.clear();
00239 for(mesh=begin;mesh!=end;++mesh)
00240 m_point_query.init_data(mesh->node_begin(),mesh->node_end());
00241 for(mesh=begin;mesh!=end;++mesh)
00242 m_point_query(mesh->tetrahedron_begin(),mesh->tetrahedron_end(),m_contacts, typename point_query_type::all_tag());
00243 std::cout << "|C| = " << m_contacts.size() << std::endl;
00244 }
00245
00246 };
00247
00248 }
00249 }
00250
00251
00252 #endif