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 #ifndef SOFA_COMPONENT_FORCEFIELD_SPHEREFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_SPHEREFORCEFIELD_INL
00027
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include <sofa/component/forcefield/ConicalForceField.h>
00030 #include <sofa/defaulttype/Quat.h>
00031
00032 #include <sofa/helper/system/config.h>
00033 #include <sofa/helper/rmath.h>
00034 #include <sofa/helper/system/gl.h>
00035 #include <sofa/helper/system/glut.h>
00036 #include <assert.h>
00037 #include <iostream>
00038
00039 namespace sofa
00040 {
00041
00042 namespace component
00043 {
00044
00045 namespace forcefield
00046 {
00047
00048 template<class DataTypes>
00049 void ConicalForceField<DataTypes>::addForce(VecDeriv& f1, const VecCoord& p1, const VecDeriv& v1)
00050 {
00051 const Coord center = coneCenter.getValue();
00052 Real d = 0.0;
00053 Real alpha = 0.0;
00054 Real length_cp_prime = 0.0;
00055 Coord p, p_prime, cp, dir, n_cp, cp_new, cp_prime, pp_prime, t;
00056 Coord n = coneHeight.getValue();
00057 n.normalize();
00058 Deriv force;
00059
00060 this->contacts.beginEdit()->clear();
00061 f1.resize(p1.size());
00062 for (unsigned int i=0; i<p1.size(); i++)
00063 {
00064 p = p1[i];
00065 if (!isIn(p))
00066 {
00067 cp = p - center;
00068
00069 if (cp.norm() > coneHeight.getValue().norm())
00070 {
00071 Real norm = cp.norm();
00072 d = norm - coneHeight.getValue().norm();
00073 dir = cp / norm;
00074 Real forceIntensity = -this->stiffness.getValue()*d;
00075 Real dampingIntensity = -this->damping.getValue()*d;
00076 force = cp*(forceIntensity/norm) - v1[i]*dampingIntensity;
00077 f1[i]+=force;
00078 Contact c;
00079 c.index = i;
00080 c.normal = cp / norm;
00081 c.pos = p;
00082 this->contacts.beginEdit()->push_back(c);
00083
00084 }
00085 else {
00086
00087 if (dot(cp,n) > 0)
00088 {
00089 n_cp = cp/cp.norm();
00090 alpha = acos(n_cp*n) - coneAngle.getValue()*3.1459/180 ;
00091 t = n.cross(cp) ;
00092 t /= t.norm();
00093 defaulttype::Quat q(t, -alpha);
00094 cp_new = q.rotate(cp);
00095
00096 cp_new.normalize();
00097 length_cp_prime = dot(cp_new, cp);
00098 cp_prime = cp_new * length_cp_prime;
00099 p_prime = cp_prime + center;
00100
00101 pp_prime = p_prime - p;
00102 d = pp_prime.norm();
00103 dir = pp_prime/pp_prime.norm();
00104
00105 }
00106
00107 else
00108 {
00109 d = cp.norm();
00110 dir = (-cp)/cp.norm();
00111 }
00112
00113 force = dir * (stiffness.getValue()*d);
00114 force += dir * (damping.getValue() * (-dot(dir,v1[i])));
00115 f1[i] += force;
00116 Contact c;
00117 c.index = i;
00118 c.normal = dir;
00119 c.pos = p;
00120
00121 this->contacts.beginEdit()->push_back(c);
00122 }
00123 }
00124 }
00125 this->contacts.endEdit();
00126 }
00127
00128 template<class DataTypes>
00129 void ConicalForceField<DataTypes>::addDForce(VecDeriv& df1, const VecDeriv& dx1)
00130 {
00131 df1.resize(dx1.size());
00132 for (unsigned int i=0; i<this->contacts.getValue().size(); i++)
00133 {
00134 const Contact& c = (*this->contacts.beginEdit())[i];
00135 assert((unsigned)c.index<dx1.size());
00136 Deriv du = dx1[c.index];
00137 Deriv dforce; dforce = -this->stiffness.getValue()*(c.normal * ((du*c.normal)));
00138 df1[c.index] += dforce;
00139 }
00140 this->contacts.endEdit();
00141 }
00142
00143 template<class DataTypes>
00144 void ConicalForceField<DataTypes>::updateStiffness( const VecCoord& )
00145 {
00146 std::cerr<<"SphereForceField::updateStiffness-not-implemented !!!"<<std::endl;
00147 }
00148
00149 template <class DataTypes>
00150 double ConicalForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00151 {
00152 std::cerr<<"ConicalForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00153 return 0;
00154 }
00155
00156 template<class DataTypes>
00157 void ConicalForceField<DataTypes>::draw()
00158 {
00159 if (!getContext()->getShowForceFields()) return;
00160 if (!bDraw.getValue()) return;
00161
00162 const Real a = coneAngle.getValue();
00163 Coord height = coneHeight.getValue();
00164 const Real h = sqrt(pow(coneHeight.getValue()[0],2) + pow(coneHeight.getValue()[1],2) + pow(coneHeight.getValue()[2],2));
00165 const Real b = tan((a/180*3.14)) * h;
00166 const Coord c = coneCenter.getValue();
00167 Coord axis = height.cross(Coord(0,0,1));
00168
00169 glEnable(GL_LIGHTING);
00170 glEnable(GL_COLOR_MATERIAL);
00171 glEnable(GL_BLEND) ;
00172 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA) ;
00173 glColor4f(color.getValue()[0],color.getValue()[1],color.getValue()[2], 0.5);
00174
00175 glPushMatrix();
00176 glTranslated(c[0], c[1], c[2]);
00177 glRotated(acos(height*Coord(0,0,1)/h)*180/3.14 ,-axis[0], axis[1], axis[2]);
00178 glRotatef(180.0,1.0,0.0,0.0);
00179 glTranslated(0.0, 0.0, -h);
00180
00181 glutSolidCone( b, h, 32, 16);
00182 glPopMatrix();
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200 glDisable(GL_BLEND) ;
00201 glDisable(GL_LIGHTING);
00202 glDisable(GL_COLOR_MATERIAL);
00203 }
00204
00205 template<class DataTypes>
00206 bool ConicalForceField<DataTypes>::isIn(Coord p)
00207 {
00208 const Coord c = coneCenter.getValue();
00209 const Coord height = coneHeight.getValue();
00210 const Real h = sqrt(pow(height[0],2) + pow(height[1],2) + pow(height[2],2));
00211 const Real distP = sqrt(pow(p[0] - c[0], 2) + pow(p[1] - c[1], 2) + pow(p[2] - c[2], 2));
00212
00213 if (distP > h){
00214 return false;
00215 }
00216 Coord vecP;
00217
00218 for(unsigned i=0 ; i<3 ; ++i)
00219 vecP[i]=p[i]-c[i];
00220
00221 if ( (acos(vecP*height/(h*distP))*180/3.14) > coneAngle.getValue() ){
00222
00223 return false;
00224 }
00225 return true;
00226 }
00227
00228 }
00229
00230 }
00231
00232 }
00233
00234 #endif