00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028 #ifndef SOFA_COMPONENT_FORCEFIELD_SPRINGFORCEFIELD_INL
00029 #define SOFA_COMPONENT_FORCEFIELD_SPRINGFORCEFIELD_INL
00030
00031 #include <sofa/component/forcefield/SpringForceField.h>
00032 #include <sofa/core/componentmodel/behavior/PairInteractionForceField.inl>
00033 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00034 #include <sofa/helper/io/MassSpringLoader.h>
00035 #include <sofa/helper/gl/template.h>
00036 #include <sofa/helper/system/config.h>
00037 #include <assert.h>
00038 #include <iostream>
00039
00040 namespace sofa
00041 {
00042
00043 namespace component
00044 {
00045
00046 namespace forcefield
00047 {
00048
00049 using std::cerr;
00050 using std::endl;
00051
00052 template<class DataTypes>
00053 SpringForceField<DataTypes>::SpringForceField(MechanicalState* mstate1, MechanicalState* mstate2, SReal _ks, SReal _kd)
00054 : Inherit(mstate1, mstate2)
00055 , ks(initData(&ks,_ks,"stiffness","uniform stiffness for the all springs"))
00056 , kd(initData(&kd,_kd,"damping","uniform damping for the all springs"))
00057 , springs(initData(&springs,"spring","pairs of indices, stiffness, damping, rest length"))
00058 {
00059 }
00060
00061 template<class DataTypes>
00062 SpringForceField<DataTypes>::SpringForceField(SReal _ks, SReal _kd)
00063 : ks(initData(&ks,_ks,"stiffness","uniform stiffness for the all springs"))
00064 , kd(initData(&kd,_kd,"damping","uniform damping for the all springs"))
00065 , springs(initData(&springs,"spring","pairs of indices, stiffness, damping, rest length"))
00066 {
00067 }
00068
00069
00070 template<class DataTypes>
00071 void SpringForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00072 {
00073 if (arg->getAttribute("filename"))
00074 this->load(arg->getAttribute("filename"));
00075 this->Inherit::parse(arg);
00076 }
00077
00078 template <class DataTypes>
00079 class SpringForceField<DataTypes>::Loader : public helper::io::MassSpringLoader
00080 {
00081 public:
00082 SpringForceField<DataTypes>* dest;
00083 Loader(SpringForceField<DataTypes>* dest) : dest(dest) {}
00084 virtual void addSpring(int m1, int m2, SReal ks, SReal kd, SReal initpos)
00085 {
00086 helper::vector<Spring>& springs = *dest->springs.beginEdit();
00087 springs.push_back(Spring(m1,m2,ks,kd,initpos));
00088 dest->springs.endEdit();
00089 }
00090 };
00091
00092 template <class DataTypes>
00093 bool SpringForceField<DataTypes>::load(const char *filename)
00094 {
00095 bool ret = true;
00096 if (filename && filename[0])
00097 {
00098 Loader loader(this);
00099 ret &= loader.load(filename);
00100 }
00101 else ret = false;
00102 return ret;
00103 }
00104
00105 template <class DataTypes>
00106 void SpringForceField<DataTypes>::init()
00107 {
00108 this->Inherit::init();
00109 }
00110
00111 template<class DataTypes>
00112 void SpringForceField<DataTypes>::addSpringForce(SReal& ener, VecDeriv& f1, const VecCoord& p1, const VecDeriv& v1, VecDeriv& f2, const VecCoord& p2, const VecDeriv& v2, int , const Spring& spring)
00113 {
00114 int a = spring.m1;
00115 int b = spring.m2;
00116 Coord u = p2[b]-p1[a];
00117 Real d = u.norm();
00118 Real inverseLength = 1.0f/d;
00119 if( d>1.0e-4 )
00120 return;
00121 u *= inverseLength;
00122 Real elongation = (Real)(d - spring.initpos);
00123 ener += elongation * elongation * spring.ks /2;
00124 Deriv relativeVelocity = v2[b]-v1[a];
00125 Real elongationVelocity = dot(u,relativeVelocity);
00126 Real forceIntensity = (Real)(spring.ks*elongation+spring.kd*elongationVelocity);
00127 Deriv force = u*forceIntensity;
00128 f1[a]+=force;
00129 f2[b]-=force;
00130 }
00131
00132 template<class DataTypes>
00133 void SpringForceField<DataTypes>::addForce(VecDeriv& f1, VecDeriv& f2, const VecCoord& x1, const VecCoord& x2, const VecDeriv& v1, const VecDeriv& v2)
00134 {
00135 f1.resize(x1.size());
00136 f2.resize(x2.size());
00137 m_potentialEnergy = 0;
00138 for (unsigned int i=0; i<this->springs.getValue().size(); i++)
00139 {
00140 this->addSpringForce(m_potentialEnergy,f1,x1,v1,f2,x2,v2, i, this->springs.getValue()[i]);
00141 }
00142 }
00143
00144 template<class DataTypes>
00145 void SpringForceField<DataTypes>::addDForce(VecDeriv&, VecDeriv&, const VecDeriv&, const VecDeriv&)
00146 {
00147 std::cerr << "SpringForceField does not support implicit integration. Use StiffSpringForceField instead.\n";
00148 }
00149
00150 template<class DataTypes>
00151 void SpringForceField<DataTypes>::draw()
00152 {
00153 if (!((this->mstate1 == this->mstate2)?getContext()->getShowForceFields():getContext()->getShowInteractionForceFields())) return;
00154 const VecCoord& p1 = *this->mstate1->getX();
00155 const VecCoord& p2 = *this->mstate2->getX();
00156
00157
00158
00159
00160 glDisable(GL_LIGHTING);
00161 bool external = (this->mstate1!=this->mstate2);
00162
00163
00164 const helper::vector<Spring>& springs = this->springs.getValue();
00165 glBegin(GL_LINES);
00166 for (unsigned int i=0; i<springs.size(); i++)
00167 {
00168 Real d = (p2[springs[i].m2]-p1[springs[i].m1]).norm();
00169 if (external)
00170 {
00171 if (d<springs[i].initpos*0.9999)
00172 glColor4f(1,0,0,1);
00173 else
00174 glColor4f(0,1,0,1);
00175 }
00176 else
00177 {
00178 if (d<springs[i].initpos*0.9999)
00179 glColor4f(1,0.5f,0,1);
00180 else
00181 glColor4f(0,1,0.5f,1);
00182 }
00183 helper::gl::glVertexT(p1[springs[i].m1]);
00184 helper::gl::glVertexT(p2[springs[i].m2]);
00185 }
00186 glEnd();
00187 }
00188
00189 }
00190
00191 }
00192
00193 }
00194
00195 #endif