00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 #include "massspringsolver.h"
00019 #include <animal/physicalSolver.inl>
00020 #include <animal/odeImplicitSolver.inl>
00021 #include<iostream>
00022 using std::cerr; using std::endl;
00023 
00024 namespace animal {
00025 
00026 template<class P, class V, class Im, class R, class I>
00027 typename MassSpringSolver<P,V,Im,R,I>::Real MassSpringSolver<P,V,Im,R,I>::_thresholdDistance=1.e-12;
00028 
00029 template<class P, class V, class Im, class R, class I>
00030 bool MassSpringSolver<P,V,Im,R,I>::_debug=false;
00031 
00032 
00033 template<class P, class V, class Im, class R, class I>
00034 MassSpringSolver<P,V,Im,R,I>::MassSpringSolver()
00035     : _links(0)
00036     , _stiffnesses(0)
00037     , _restLengths(0)
00038     , _own_restLengths(false)
00039     , _isotropy(0.03)
00040 {
00041 
00042 }
00043 
00044 template<class P,class V,class Im,class R,class I>
00045 void MassSpringSolver<P,V,Im,R,I>::solveODE(
00046     Positions& pos,
00047     Vector& vel,
00048     Real dt
00049 )
00050 {
00051   
00052     _OdeImplicitSolver::solveODE(pos,vel,dt);
00053     this->applyExponentialDamping(vel,dt);
00054 }
00055 
00056 
00057 template<class P, class V, class Im, class R, class I>
00058 MassSpringSolver<P,V,Im,R,I>::~MassSpringSolver()
00059 {
00060     if( _own_restLengths ) delete _restLengths;
00061 }
00062 
00063 
00064 
00065 
00066 
00068 template<class P, class V, class Im, class R, class I>
00069 void MassSpringSolver<P,V,Im,R,I>::setMethod( int m ){
00070     this->_OdeImplicitSolver::setMethod(m);
00071 }
00073 template<class P, class V, class Im, class R, class I>
00074 int MassSpringSolver<P,V,Im,R,I>::getMethod() const {
00075     return this->_OdeImplicitSolver::method();
00076 }
00078 template<class P, class V, class Im, class R, class I>
00079 void MassSpringSolver<P,V,Im,R,I>::setIsotropy( Real isot ){
00080     this->_isotropy = isot;
00081 }
00083 template<class P, class V, class Im, class R, class I>
00084 typename MassSpringSolver<P,V,Im,R,I>::Real MassSpringSolver<P,V,Im,R,I>::getIsotropy() const {
00085     return this->_isotropy;
00086 }
00088 template<class P, class V, class Im, class R, class I>
00089 const typename MassSpringSolver<P,V,Im,R,I>::Real& MassSpringSolver<P,V,Im,R,I>::get_common_damping_ratio(){
00090     return this->_dampingRatio;
00091 }
00093 template<class P, class V, class Im, class R, class I>
00094 void MassSpringSolver<P,V,Im,R,I>::set_common_damping_ratio( const Real& _newVal){
00095     this->_dampingRatio = _newVal;
00096 }
00097 
00099 template<class P, class V, class Im, class R, class I>
00100 void MassSpringSolver<P,V,Im,R,I>::set_spring_indices( VecIndex* newVal){ _links=newVal; }
00101 
00103 template<class P, class V, class Im, class R, class I>
00104 void MassSpringSolver<P,V,Im,R,I>::set_stiffnesses( VecReal* newVal){ _stiffnesses = newVal; }
00105 
00107 
00108 
00109 
00110 
00111 
00112 
00113 
00114 
00115 
00116 
00117 
00118 
00119 
00120 
00121 
00122 
00123 
00124 
00125 
00126 
00127 
00128 
00129 
00130 
00131 
00132 
00133 
00134 
00135 
00136 
00138 template<class P, class V, class Im, class R, class I>
00139 void MassSpringSolver<P,V,Im,R,I>::accumulateSpringForce(Vec& fa, Vec& fb,
00140     const Vec& pa, const Vec& pb,
00141     const Vec& va, const Vec& vb,
00142     const Real& stiffness, const Real& dampingRatio, const Real& restLength)
00143 {
00144    Real distance;
00145    Vec direction;
00146    if( computeDistanceAndDirection(distance, direction, pa, pb ) )
00147    {
00148    Real elongation = distance-restLength;
00149          Vec relativeVelocity = vb;
00150          v_meq(relativeVelocity,va);
00151          Real elongationVelocity = v_dot(direction,relativeVelocity);
00152          Vec f = direction;
00153          v_teq( f, stiffness*(elongation + dampingRatio*elongationVelocity) );
00154          v_peq( fa, f );
00155          v_meq( fb, f );
00156 
00157         if (_debug){
00158         cerr << ", point " << pa <<", force += "<< fa << endl   
00159             << ", point " << pb <<", force -= "<< fb << endl
00160             << ", distance = " << distance <<", elongation = "<< elongation <<endl
00161             << ", direction = " << direction << endl
00162         << endl;
00163         }
00164    }
00165 }
00166 
00168 template<class P, class Vec, class Im, class Real, class I>
00169 void MassSpringSolver<P,Vec,Im,Real,I>::accumulateSpringForceAndGradientMatrix
00170     ( Vec& fa, Vec& fb, Vec& grad,
00171     const Vec& pa, const Vec& pb,
00172     const Vec& va, const Vec& vb,
00173     const Real& stiffness, const Real& dampingRatio, const Real& restLength)
00174 {
00175    Real distance;
00176    Vec direction;
00177    if( computeDistanceAndDirection(distance, direction, pa, pb) )
00178    {
00179      grad = direction;
00180          Real elongation = distance-restLength;
00181          Vec relativeVelocity = vb;
00182          v_meq(relativeVelocity,va);
00183          Real elongationVelocity = v_dot(direction,relativeVelocity);
00184          Vec f = direction;
00185          v_teq( f, stiffness*(elongation + dampingRatio*elongationVelocity) );
00186          
00187          v_peq( fa, f );
00188          v_meq( fb, f );
00189    }
00190 }
00191 
00194 template<class P, class V, class Im, class R, class I>
00195 bool MassSpringSolver<P,V,Im,R,I>::computeDistanceAndDirection(Real& d, Vec& u,
00196 const Vec& pa, const Vec& pb){
00197     u = pb-pa;
00198     d = v_norm(u);
00199     
00200     if( d<get_thresholdDistance() ) return false;
00201     v_teq( u, 1/d);
00202     return true;
00203 }
00204 
00206 template<class P, class V, class Im, class R, class I>
00207 void MassSpringSolver<P,V,Im,R,I>::computeForces( Vector& f, const Positions& p, const Vector& v)
00208 {
00209     _PhysicalSolver::computeForces(f,p,v);
00210     
00211   assert( size(*_links)%2 ==0);
00212     for( unsigned int i=0; i<_links->size(); i+=2 )
00213     {
00214     Index& a = (*_links)[i  ];
00215     Index& b = (*_links)[i+1];
00216         if (_debug){
00217             cerr << "index du point a= " << a << endl
00218             << "index du point b= " << b << endl;
00219         }
00220         accumulateSpringForce( f[a], f[b], p[a], p[b], v[a], v[b], (*_stiffnesses)[i/2], _dampingRatio, (*_restLengths)[i/2] );
00221     }
00222    
00223 }
00224 
00226 template<class P, class V, class Im, class R, class I>
00227 void MassSpringSolver<P,V,Im,R,I>::computeAccelerations( Vector& a, const Positions& p, const Vector& v)
00228 {
00229     _PhysicalSolver::computeAccelerations(a,p,v);
00230     
00231 }
00232 
00234 template<class P, class V, class Im, class R, class I>
00235 void MassSpringSolver<P,V,Im,R,I>::computeAccelerationsAndStiffness( Vector& f, const Positions& p, const Vector& v)
00236 {
00237       
00238     _PhysicalSolver::computeForces(f,p,v);
00239     
00240   assert( size(*_links)%2 ==0);
00241   assert( size(*_stiffnesses)==size(*_links)/2 );
00242   assert( size(*_restLengths)==size(*_links)/2 );
00243   assert( size(p)==size(f) );
00244   assert( size(v)==size(f) );
00245   
00246   
00247   _directions.resize( size(*_links)/2 );
00248     for( unsigned int i=0; i<_links->size(); i+=2 )
00249     {
00250     Index& a = (*_links)[i  ];
00251     Index& b = (*_links)[i+1];
00252         accumulateSpringForceAndGradientMatrix(
00253             f[a],
00254             f[b],
00255             _directions[i/2],
00256             p[a],
00257             p[b],
00258             v[a],
00259             v[b],
00260             (*_stiffnesses)[i/2],
00261             _dampingRatio,
00262             (*_restLengths)[i/2] );
00263     }
00264   
00265 
00266   this->applyForces(f,f);
00267   
00268 
00269   this->applyGravity(f);
00270   
00271 
00272     
00273 
00274 }
00275 
00276 
00277 
00278 
00279 
00280 
00281 
00282 
00283 
00284 
00285 
00286 
00287 
00288 
00289 
00290 
00291 
00292 
00293 
00294 
00295 
00296 
00297 
00298 
00299 
00300 
00301 
00302 
00303 
00304 
00305 
00306 
00307 
00308 
00309 
00310 
00311 
00312 
00313 
00314 
00315 
00320 template<class Positions, class Vector, class Im, class R, class I>
00321     void MassSpringSolver<Positions,Vector,Im,R,I>
00322 	::applyForces( Vector& a, const Vector& f)
00323     {
00324     this->_PhysicalSolver::applyForces(a,f);
00325     }
00326 
00327     
00328 
00329 
00330 
00331 
00332 
00333 
00334 
00335 
00336 
00337 
00338 
00339 
00340 
00341 
00342 
00343 
00344 
00345 
00346 
00347 
00348 
00349 
00350 
00351 
00352 
00353 
00354 
00355 
00356 
00357 
00358 
00359 
00360 
00361 
00362 
00363 
00364 
00365 
00366 
00367 
00368 
00369 
00370 
00371 
00372 
00373 
00374 
00375 
00376 
00377 
00378 
00379 
00380 
00381 
00382 
00383 
00384 
00385 
00386 
00387 
00388 
00394 template<class Positions, class Vector, class Im, class Real, class I>
00395     void MassSpringSolver<Positions,Vector,Im,Real,I>
00396 	::v_eq_h_dfdx_x( Vector& v, Real h, const Vector& x )
00397     {
00398         v_assign( v, Value<Vec>::zero() );
00399         v_peq_h_dfdx_x(v,h,x);
00400     }
00401 
00408 template<class Positions, class Vector, class Im, class Real, class I>
00409     void MassSpringSolver<Positions,Vector,Im,Real,I>
00410 	::v_peq_h_dfdx_x( Vector& v, Real h, const Vector& x )
00411     {
00412      assert( size(v)==size(x) );
00413      assert( size((*_stiffnesses))==size(_directions) );
00414      assert( size(_directions)==size(*_links)/2 );
00415      
00416 
00417          for( unsigned int i=0, iend=size(_directions); i!=iend; ++i )
00418          {
00419             Real u; Vec p, piso;
00420             Real hk = -h * (*_stiffnesses)[i];
00421             Real hiso = _isotropy * hk;
00422             Real hh = hk -  hiso;
00423             std::size_t i1=(*_links)[i*2], i2=(*_links)[(i*2)+1];
00424             
00425 
00426             
00427             
00428             u = v_dot(_directions[i],x[i1]);
00429             v_eq_ab( p, hh*u, _directions[i] );
00430             v_peq( v[i1], p );
00431             v_meq( v[i2], p );
00432             
00433             v_eq_ab( piso, hiso, x[i1] );
00434             v_peq( v[i1], piso );
00435             v_meq( v[i2], piso );
00436 
00437             
00438             
00439             u = v_dot(_directions[i],x[i2]);
00440             v_eq_ab( p, hh*u, _directions[i] );
00441             v_peq( v[i2], p );
00442             v_meq( v[i1], p );
00443             
00444             v_eq_ab( piso, hiso, x[i2] );
00445             v_peq( v[i2], piso );
00446             v_meq( v[i1], piso );
00447          }
00448 
00449     }
00450 
00451 }