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_INTERACTION_ELLIPSOIDFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_INTERACTION_ELLIPSOIDFORCEFIELD_INL
00027
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include "InteractionEllipsoidForceField.h"
00030 #include <sofa/helper/gl/template.h>
00031 #include <sofa/helper/system/config.h>
00032 #include <sofa/helper/system/glut.h>
00033 #include <sofa/helper/rmath.h>
00034 #include <assert.h>
00035 #include <iostream>
00036
00037 namespace sofa
00038 {
00039
00040 namespace component
00041 {
00042
00043 namespace interactionforcefield
00044 {
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068 template<class DataTypes1, class DataTypes2>
00069 void InteractionEllipsoidForceField<DataTypes1, DataTypes2>::initCalcF()
00070 {
00071 vars.r = this->vradius.getValue();
00072 vars.stiffness = this->stiffness.getValue();
00073 vars.stiffabs = helper::rabs(vars.stiffness);
00074 for (int j=0; j<N; j++) vars.inv_r2[j] = 1/(vars.r[j]*vars.r[j]);
00075
00076
00077
00078 }
00079
00080 template<class DataTypes1, class DataTypes2>
00081 bool InteractionEllipsoidForceField<DataTypes1, DataTypes2>::calcF(const Coord1& p1, const Deriv1& v1, Deriv1 &f1, Mat& dfdx)
00082 {
00083 Coord1 dp = p1 - vars.center;
00084 Real1 norm2 = 0;
00085 for (int j=0; j<N; j++) norm2 += (dp[j]*dp[j])*vars.inv_r2[j];
00086
00087 if ((norm2-1)*vars.stiffness<0)
00088 {
00089
00090
00091
00092
00093 Real1 norm = helper::rsqrt(norm2);
00094 Real1 v = norm-1;
00095 Deriv1 grad;
00096 for (int j=0; j<N; j++) grad[j] = dp[j]*vars.inv_r2[j];
00097 Real1 gnorm2 = grad.norm2();
00098 Real1 gnorm = helper::rsqrt(gnorm2);
00099
00100 Real1 forceIntensity = -vars.stiffabs*v/gnorm;
00101 Real1 dampingIntensity = this->damping.getValue()*helper::rabs(v);
00102 Deriv1 force = grad*forceIntensity - v1*dampingIntensity;
00103 f1=force;
00104 Real1 fact1 = -vars.stiffabs / (norm * gnorm);
00105 Real1 fact2 = -vars.stiffabs*v / gnorm;
00106 Real1 fact3 = -vars.stiffabs*v / gnorm2;
00107 for (int ci = 0; ci < N; ++ci)
00108 {
00109 for (int cj = 0; cj < N; ++cj)
00110 dfdx[ci][cj] = grad[ci]*grad[cj] * (fact1 + fact3*vars.inv_r2[cj]);
00111 dfdx[ci][ci] += fact2*vars.inv_r2[ci];
00112 }
00113 return true;
00114 }
00115 else
00116 return false;
00117 }
00118
00119 template<class DataTypes1, class DataTypes2>
00120 void InteractionEllipsoidForceField<DataTypes1, DataTypes2>::addForce(VecDeriv1& f1, VecDeriv2& f2,
00121 const VecCoord1& p1, const VecCoord2& p2,
00122 const VecDeriv1& v1, const VecDeriv2& v2)
00123 {
00124
00125
00126 X1 = p1;
00127 X2 = p2;
00128
00129 vars.pos6D = p2[object2_dof_index.getValue()];
00130 Quat Cq = vars.pos6D.getOrientation();
00131 Vec3d Cx = (Coord1) vars.pos6D.getCenter();
00132 Deriv2 V6D = v2[object2_dof_index.getValue()];
00133 Vec3d Cv = (Vec3d) V6D.getVCenter();
00134 Cv.clear();
00135
00137 _orientation = Cq;
00138
00139
00141
00142
00143 if(_update_pos_relative)
00144 {
00145
00146
00147
00148 vars.center = (Vec3d) center.getValue();
00149
00150 Cv.clear();
00151 }
00152
00153 initCalcF();
00154
00155
00156 sofa::helper::vector<Contact>* contacts = this->contacts.beginEdit();
00157 contacts->clear();
00158 f1.resize(p1.size());
00159 for (unsigned int i=0; i<p1.size(); i++)
00160 {
00161 Coord1 p1Xform = Cq.inverseRotate(p1[i] - Cx);
00162
00163 Deriv1 v1Xform = Cq.inverseRotate(v1[i]);
00164 Deriv1 f1Xform;
00165 f1Xform.clear();
00166 Mat dfdx;
00167 if (calcF(p1Xform, v1Xform, f1Xform, dfdx) && !_update_pos_relative)
00168 {
00169
00170
00171 Contact c;
00172 c.pos = p1[i];
00173 c.index = i;
00174 c.m = dfdx;
00175
00176 Vec3d contactForce = Cq.rotate(f1Xform);
00177 f1[i]+=contactForce;
00178 f2[object2_dof_index.getValue()].getVCenter() -= contactForce;
00179 c.bras_levier = p1[i] - Cx;
00180
00181 contacts->push_back(c);
00182
00183
00184
00185
00186
00187
00188
00189
00190 }
00191 }
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205
00206 if(_update_pos_relative)
00207 {
00208 f2[object2_dof_index.getValue()].getVCenter().clear();
00209 f2[object2_dof_index.getValue()].getVOrientation().clear();
00210 _update_pos_relative = false;
00211 }
00212 this->contacts.endEdit();
00213 }
00214
00215 template<class DataTypes1, class DataTypes2>
00216 void InteractionEllipsoidForceField<DataTypes1, DataTypes2>::addForce2(VecDeriv1& f1, VecDeriv2& f2,
00217 const VecCoord1& p1, const VecCoord2& p2,
00218 const VecDeriv1& v1, const VecDeriv2& )
00219 {
00220
00221 Quat Cq = p2[object2_dof_index.getValue()].getOrientation();
00222 Vec3d Cx = (Coord1) p2[object2_dof_index.getValue()].getCenter();
00223
00224 f1.clear();
00225 f2.clear();
00226 f1.resize(p1.size());
00227 f2.resize(p2.size());
00228 for (unsigned int i=0; i<p1.size(); i++)
00229 {
00230 Coord1 p1Xform = Cq.inverseRotate(p1[i] - Cx);
00231
00232 Deriv1 v1Xform = Cq.inverseRotate(v1[i]);
00233 Deriv1 f1Xform;
00234 f1Xform.clear();
00235 Mat dfdx;
00236 if (calcF(p1Xform, v1Xform, f1Xform, dfdx))
00237 {
00238
00239
00240 Vec3d contactForce = Cq.rotate(f1Xform);
00241 Vec3d bras_levier;
00242 bras_levier = p1[i] - Cx;
00243 f1[i]+=contactForce;
00244 f2[object2_dof_index.getValue()].getVCenter() -= contactForce;
00245 f2[object2_dof_index.getValue()].getVOrientation() -= bras_levier.cross(contactForce);
00246
00247
00248 }
00249 }
00250
00251
00252
00253 }
00254
00255
00256 template<class DataTypes1, class DataTypes2>
00257 void InteractionEllipsoidForceField<DataTypes1, DataTypes2>::addDForce(VecDeriv1& df1, VecDeriv2& df2, const VecDeriv1& dx1, const VecDeriv2& dx2)
00258 {
00259
00260 df1.resize(dx1.size());
00261 df2.resize(dx2.size());
00262 const sofa::helper::vector<Contact>& contacts = this->contacts.getValue();
00263
00264 for (unsigned int i=0; i<contacts.size(); i++)
00265 {
00266 const Contact& c = contacts[i];
00267 assert((unsigned)c.index<dx1.size());
00268 Vec3d du;
00269 du = (Vec3d) dx1[c.index] - (Vec3d) dx2[object2_dof_index.getValue()].getVCenter();
00270 Deriv1 dforce = c.m * _orientation.inverseRotate(du);
00271 Vec3d DF = _orientation.rotate(dforce);
00272 df1[c.index] += DF;
00273 df2[object2_dof_index.getValue()].getVCenter() -= DF;
00274
00275
00276 }
00277
00278
00279 }
00280
00281 template <class DataTypes1, class DataTypes2>
00282 double InteractionEllipsoidForceField<DataTypes1, DataTypes2>::getPotentialEnergy(const VecCoord1& , const VecCoord2& )
00283 {
00284 std::cerr<<"InteractionEllipsoidForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00285 return 0;
00286 }
00287
00288 template<class DataTypes1, class DataTypes2>
00289 void InteractionEllipsoidForceField<DataTypes1, DataTypes2>::draw()
00290 {
00291 if (!getContext()->getShowForceFields()) return;
00292 if (!bDraw.getValue()) return;
00293
00294 Real1 cx1=0, cy1=0, cz1=0;
00295 Real1 cx2=0, cy2=0, cz2=0;
00296 DataTypes1::get(cx1, cy1, cz1, vars.center );
00297
00298
00299
00300
00301
00302 cx2=vars.pos6D.getCenter()[0];
00303 cy2=vars.pos6D.getCenter()[1];
00304 cz2=vars.pos6D.getCenter()[2];
00305
00306
00307 Real1 rx=1, ry=1, rz=1;
00308 DataTypes1::get(rx, ry, rz, vradius.getValue());
00309 glEnable(GL_CULL_FACE);
00310 glEnable(GL_LIGHTING);
00311 glEnable(GL_COLOR_MATERIAL);
00312 glColor3f(color.getValue()[0],color.getValue()[1],color.getValue()[2]);
00313
00314
00315 Quat q=vars.pos6D.getOrientation();
00316 #ifdef SOFA_FLOAT
00317 GLfloat R[4][4];
00318 #else
00319 GLdouble R[4][4];
00320 #endif
00321 Quat q1=q.inverse();
00322 q1.buildRotationMatrix(R);
00323
00324 glPushMatrix();
00325 helper::gl::glTranslate(cx2, cy2, cz2);
00326 helper::gl::glMultMatrix( &(R[0][0]) );
00327 helper::gl::glTranslate(cx1, cy1, cz1);
00328 helper::gl::glScale(rx, ry, (stiffness.getValue()>0?rz:-rz));
00329 glutSolidSphere(1,32,16);
00330
00331
00332 glPopMatrix();
00333 glDisable(GL_CULL_FACE);
00334 glDisable(GL_LIGHTING);
00335 glDisable(GL_COLOR_MATERIAL);
00336
00337 const sofa::helper::vector<Contact>& contacts = this->contacts.getValue();
00338 for (unsigned int i=0; i<contacts.size(); i++)
00339 {
00340 glPointSize(10);
00341 glColor4f (1,0.5,0.5,1);
00342 glBegin (GL_POINTS);
00343 glVertex3d(contacts[i].pos[0],contacts[i].pos[1],contacts[i].pos[2] );
00344 glEnd();
00345 }
00346
00347 }
00348
00349
00350 }
00351
00352 }
00353
00354 }
00355
00356 #endif