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_CORE_COMPONENTMODEL_COLLISION_CONTACTCORRECTION_INL
00026 #define SOFA_CORE_COMPONENTMODEL_COLLISION_CONTACTCORRECTION_INL
00027
00028 #include "PrecomputedConstraintCorrection.h"
00029 #include <sofa/defaulttype/RigidTypes.h>
00030 #include <sofa/simulation/tree/GNode.h>
00031 #include <sofa/component/mass/UniformMass.h>
00032 #include <sofa/simulation/common/MechanicalVisitor.h>
00033
00034
00035 #include <sofa/component/odesolver/CGImplicitSolver.h>
00036
00037 #include <sstream>
00038 #include <list>
00039
00040 namespace sofa
00041 {
00042
00043 namespace component
00044 {
00045
00046 namespace constraint
00047 {
00048 #define MAX_NUM_CONSTRAINT_PER_NODE 100
00049 #define EPS_UNITARY_FORCE 0.01
00050
00051 using namespace sofa::component::odesolver;
00052
00053 template<class DataTypes>
00054 PrecomputedConstraintCorrection<DataTypes>::PrecomputedConstraintCorrection(behavior::MechanicalState<DataTypes> *mm)
00055 : _rotations(false)
00056 , f_rotations(initDataPtr(&f_rotations,&_rotations,"rotations",""))
00057 , _restRotations(false)
00058 , f_restRotations(initDataPtr(&f_restRotations,&_restRotations,"restDeformations",""))
00059 , mstate(mm)
00060 , appCompliance(NULL)
00061 , _indexNodeSparseCompliance(NULL)
00062 {
00063 }
00064
00065 template<class DataTypes>
00066 PrecomputedConstraintCorrection<DataTypes>::~PrecomputedConstraintCorrection()
00067 {
00068 if(appCompliance != NULL)
00069 delete [] appCompliance;
00070 if(_indexNodeSparseCompliance != NULL)
00071 delete [] _indexNodeSparseCompliance;
00072 }
00073
00074
00075
00077
00079
00080 template<class DataTypes>
00081 void PrecomputedConstraintCorrection<DataTypes>::init()
00082 {
00083
00084 f_rotations.beginEdit();
00085 f_restRotations.beginEdit();
00086 mstate = dynamic_cast< behavior::MechanicalState<DataTypes>* >(getContext()->getMechanicalState());
00087 const VecDeriv& v0 = *mstate->getV();
00088
00089 nbNodes = v0.size();
00090
00091 if (nbNodes==0){
00092 std::cout << "WARNING : No degree of freedom" << endl;;
00093 return;
00094 }
00095 dof_on_node = v0[0].size();
00096
00097
00098 nbRows = nbNodes*dof_on_node;
00099 nbCols = nbNodes*dof_on_node;
00100 std::cout << "size : " << nbRows << " " << nbCols << std::endl;
00101 appCompliance = new Real[nbRows * nbCols];
00102
00103
00104 double dt = this->getContext()->getDt();
00105
00106 std::stringstream ss;
00107
00108 ss << this->getContext()->getName() << ".comp";
00109
00110 std::ifstream compFileIn(ss.str().c_str(), std::ifstream::binary);
00111
00112 std::cout << "try to open : " << ss.str() << endl;
00113
00114 if(compFileIn.good())
00115 {
00116 std::cout << "file open : " << ss.str() << " compliance being loaded" << endl;
00117
00118 compFileIn.read((char*)appCompliance, nbCols * nbRows*sizeof(double));
00119 compFileIn.close();
00120 }
00121 else
00122 {
00123 std::cout << "can not open : " << ss.str() << " compliance being built" << endl;
00124
00125
00126 const Vec3d gravity = this->getContext()->getGravityInWorld();
00127 const Vec3d gravity_zero(0.0,0.0,0.0);
00128 this->getContext()->setGravityInWorld(gravity_zero);
00129
00130
00131 VecDeriv& force = *mstate->getExternalForces();
00132 force.clear();
00133 force.resize(nbNodes);
00134
00135
00136 CGImplicitSolver* odeSolver = dynamic_cast<CGImplicitSolver*>(dynamic_cast<simulation::tree::GNode *>(this->getContext())->solver[0]);
00137
00138 if (odeSolver==NULL){
00139 std::cout << "WARNING : PrecomputedContactCorrection Must be associated with CGImplicitSolver for the precomputation " << std::endl;
00140 std::cout << "No Precomputation " << std::endl;
00141 return;
00142 }
00143 else
00144 std::cout << "use solver CGImplicitSolver " << std::endl;
00145
00147 double buf_tolerance = (double) odeSolver->f_tolerance.getValue();
00148 int buf_maxIter = (int) odeSolver->f_maxIter.getValue();
00149 double buf_threshold = (double) odeSolver->f_smallDenominatorThreshold.getValue();
00150 odeSolver->f_tolerance.setValue(1e-20);
00151 odeSolver->f_maxIter.setValue(500);
00152 odeSolver->f_smallDenominatorThreshold.setValue(1e-35);
00154
00155 VecDeriv& velocity = *mstate->getV();
00156 VecCoord& pos=*mstate->getX();
00157 VecCoord& pos0=*mstate->getX0();
00158
00159
00160
00161 for(unsigned int f = 0 ; f < nbNodes ; f++){
00162 std::cout << "inverse cols node : " << f << std::endl;
00163 Deriv unitary_force;
00164
00165 for (unsigned int i=0; i<dof_on_node; i++) {
00166 unitary_force.clear();
00167 unitary_force[i]=1.0;
00168 force[f] = unitary_force;
00170 velocity.clear();
00171 velocity.resize(nbNodes);
00172 for (unsigned int n=0; n<nbNodes; n++)
00173 pos[n] = pos0[n];
00175
00176
00177
00178 odeSolver->solve(dt);
00179 velocity = *mstate->getV();
00180
00181 for (unsigned int v=0; v<nbNodes; v++){
00182
00183 for (unsigned int j=0; j<dof_on_node; j++) {
00184 appCompliance[(v*dof_on_node+j)*nbCols + (f*dof_on_node+i) ] = velocity[v][j] / unitary_force[i];
00185 }
00186 }
00187 }
00188 unitary_force.clear();
00189 force[f] = unitary_force;
00190 }
00192
00193 this->getContext()->setGravityInWorld(gravity);
00194 odeSolver->f_tolerance.setValue(buf_tolerance);
00195 odeSolver->f_maxIter.setValue(buf_maxIter);
00196 odeSolver->f_smallDenominatorThreshold.setValue(buf_threshold);
00198 std::ofstream compFileOut(ss.str().c_str(), std::fstream::out | std::fstream::binary);
00199 compFileOut.write((char*)appCompliance, nbCols * nbRows*sizeof(double));
00200 compFileOut.close();
00201 }
00202
00203
00204 _indexNodeSparseCompliance = new int[v0.size()];
00205 _sparseCompliance.resize(v0.size()*MAX_NUM_CONSTRAINT_PER_NODE);
00206
00207
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220 std::cout << "----------- Test Quaternions --------------" << std::endl;
00221
00222
00223 Quat q0(0,0,-0.7071067811865475, 0.7071067811865475);
00224 q0.normalize();
00225
00226
00227
00228 Quat q_q0(-0.7071067811865475,0,0,0.7071067811865475);
00229 q_q0.normalize();
00230
00231
00232
00233 Quat q = q0 * q_q0;
00234 q.normalize();
00235
00236
00237 std::cout<<"VecX = "<<q.rotate( Vec3d(1.0,0.0,0.0) )<<std::endl;
00238 std::cout<<"VecY = "<<q.rotate( Vec3d(0.0,1.0,0.0) )<<std::endl;
00239 std::cout<<"VecZ = "<<q.rotate( Vec3d(0.0,0.0,1.0) )<<std::endl;
00240
00241
00242
00243
00244 Quat q_test = q * q0.inverse();
00245
00246 std::cout<<"q_test = "<<q_test<<std::endl;
00247
00248 std::cout<<"Alpha = "<<q_test.toEulerVector()<< " doit valoir une rotation de Pi/2 autour de l'axe y"<<std::endl;
00249
00250
00251
00252
00253
00254
00255
00256
00257 }
00258
00259 template<>
00260 PrecomputedConstraintCorrection<defaulttype::Vec3Types>::~PrecomputedConstraintCorrection()
00261 {
00262 delete [] appCompliance;
00263 }
00264
00265
00266 template<class DataTypes>
00267 void PrecomputedConstraintCorrection<DataTypes>::getCompliance(defaulttype::BaseMatrix* W)
00268 {
00269
00270 VecConst& constraints = *mstate->getC();
00271
00272 unsigned int numConstraints = constraints.size();
00273
00275
00277
00279 if(_rotations)
00280 rotateConstraints();
00282
00283
00285 std::list<int> activeDof;
00286 for(unsigned int c1 = 0; c1 < numConstraints; c1++)
00287 {
00288 for(unsigned int i = 0; i < constraints[c1].size(); i++)
00289 activeDof.push_back(constraints[c1][i].index);
00290 }
00291
00292
00293 activeDof.sort();
00294 activeDof.unique();
00295
00296
00297
00298
00300 unsigned int offset, offset2;
00301 unsigned int i,j,ii,jj, curRowConst, curColConst, sizeCurColConst, sizeCurRowConst, it;
00302 Deriv Vbuf;
00303 int indexCurColConst, indexCurRowConst;
00304 it=0;
00305
00307
00308 std::list<int>::iterator IterateurListe;
00309 for(IterateurListe=activeDof.begin();IterateurListe!=activeDof.end();IterateurListe++){
00310 int NodeIdx = (*IterateurListe);
00311 _indexNodeSparseCompliance[NodeIdx]=it;
00312 for(curColConst = 0; curColConst < numConstraints; curColConst++)
00313 {
00314 sizeCurColConst = constraints[curColConst].size();
00315 indexCurColConst = mstate->getConstraintId()[curColConst];
00316
00317 const Const& c2 = constraints[curColConst];
00318
00319 Vbuf.clear();
00320 for(j = 0; j < sizeCurColConst; j++)
00321 {
00322 const Deriv& n2 = c2[j].data;
00323 offset = dof_on_node*(NodeIdx * nbCols + c2[j].index);
00324
00325 for (ii=0; ii<dof_on_node; ii++)
00326 {
00327 offset2 = offset+ii*nbCols;
00328 for (jj=0; jj<dof_on_node; jj++)
00329 {
00330 Vbuf[ii] += appCompliance[offset2 + jj] * n2[jj];
00331 }
00332 }
00333 }
00334 _sparseCompliance[it]=Vbuf;
00335 it++;
00336 }
00337 }
00338
00339
00340 for(curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00341 {
00342 sizeCurRowConst = constraints[curRowConst].size();
00343 indexCurRowConst = mstate->getConstraintId()[curRowConst];
00344
00345 const Const& c1 = constraints[curRowConst];
00346 for(i = 0; i < sizeCurRowConst; i++)
00347 {
00348
00349 const int NodeIdx = c1[i].index;
00350 const Deriv& n1 = c1[i].data;
00351
00352 unsigned int toto =(unsigned int) _indexNodeSparseCompliance[NodeIdx];
00353
00354 for(curColConst = curRowConst; curColConst < numConstraints; curColConst++)
00355 {
00356 indexCurColConst = mstate->getConstraintId()[curColConst];
00357 double w = _sparseCompliance[toto + curColConst]*n1;
00358
00359
00360 W->add(indexCurRowConst, indexCurColConst, w);
00361 if (indexCurRowConst != indexCurColConst)
00362 W->add(indexCurColConst, indexCurRowConst, w);
00363 }
00364 }
00365
00366
00367
00368
00369
00370
00371
00372
00373 }
00374 }
00375
00376 template<class DataTypes>
00377 void PrecomputedConstraintCorrection<DataTypes>::applyContactForce(const defaulttype::BaseVector *f)
00378 {
00379 VecDeriv& force = *mstate->getExternalForces();
00380 VecConst& constraints = *mstate->getC();
00381 unsigned int numConstraints = constraints.size();
00382
00383 VecDeriv& dx = *mstate->getDx();
00384 VecCoord& x = *mstate->getX();
00385 VecDeriv& v = *mstate->getV();
00386 VecDeriv v_free = *mstate->getVfree();
00387 VecCoord x_free = *mstate->getXfree();
00388 double dt = this->getContext()->getDt();
00389
00390
00391
00392
00393 dx.clear();
00394 dx.resize(v.size());
00395
00396 force.clear();
00397 force.resize(x_free.size());
00398
00399 std::list<int> activeDof;
00400
00401
00402 for(unsigned int c1 = 0; c1 < numConstraints; c1++)
00403 {
00404 int indexC1 = mstate->getConstraintId()[c1];
00405
00406 double fC1 = (Real)f->element(indexC1);
00407
00408
00409 if (fC1 != 0.0)
00410 {
00411
00412 const int sizeC1 = constraints[c1].size();
00413 for(int i = 0; i < sizeC1; i++)
00414 {
00415
00416
00417 const Deriv& toto = constraints[c1][i].data * fC1;
00418 force[constraints[c1][i].index] += toto;
00419 activeDof.push_back(constraints[c1][i].index);
00420 }
00421 }
00422 }
00423
00424 activeDof.sort();
00425 activeDof.unique();
00426
00427
00428
00429
00430 std::list<int>::iterator IterateurListe;
00431 unsigned int i;
00432 unsigned int offset, offset2;
00433 for(IterateurListe=activeDof.begin();IterateurListe!=activeDof.end();IterateurListe++){
00434 int f = (*IterateurListe);
00435
00436 for (i=0; i< dof_on_node; i++)
00437 {
00438 Fbuf[i] = force[f][i];
00439 }
00440 for(unsigned int v = 0 ; v < dx.size() ; v++)
00441 {
00442 offset = v * dof_on_node * nbCols + f*dof_on_node;
00443 for (unsigned int j=0; j< dof_on_node; j++)
00444 {
00445 offset2 = offset+ j*nbCols;
00446 DXbuf=0.0;
00447 for (i=0; i< dof_on_node; i++)
00448 {
00449 DXbuf += appCompliance[ offset2 + i ] * Fbuf[i];
00450 }
00451 dx[v][j]+=DXbuf;
00452 }
00453 }
00454 }
00455
00456
00457 force.clear();
00458 force.resize(x_free.size());
00459
00460 if(_rotations)
00461 rotateResponse();
00462
00463
00464 for (unsigned int i=0; i< dx.size(); i++)
00465 {
00466
00467 x[i] = x_free[i];
00468 v[i] = v_free[i];
00469
00470 x[i] += dx[i];
00471 v[i] += dx[i]*(1/dt);
00472 }
00473 }
00474
00475
00476
00477
00478
00479
00480
00481
00482
00483
00484
00485
00486
00487
00488
00489
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505
00506
00507
00508
00509
00510
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531
00532
00533
00534
00535
00536
00537
00538
00539
00540
00541
00542
00543
00544
00545
00546
00547
00548
00549
00550
00551
00552
00553
00554
00555
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
00570
00571
00572
00573
00574
00575
00576
00577
00578
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594
00595
00596
00597
00598 template<class DataTypes>
00599 void PrecomputedConstraintCorrection<DataTypes>::resetContactForce()
00600 {
00601 VecDeriv& force = *mstate->getExternalForces();
00602 for( unsigned i=0; i<force.size(); ++i )
00603 force[i] = Deriv();
00604 }
00605
00606 template<class DataTypes>
00607 void PrecomputedConstraintCorrection<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00608 {
00609 this->Inherit::parse(arg);
00610 }
00611 #ifndef SOFA_FLOAT
00612
00613 template<>
00614 void PrecomputedConstraintCorrection<defaulttype::Vec3dTypes>::rotateConstraints()
00615 {
00616 VecConst& constraints = *mstate->getC();
00617 unsigned int numConstraints = constraints.size();
00618
00619 simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00620
00621 sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes>* forceField = NULL;
00622 if (node != NULL)
00623 {
00624
00625 forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes> > ();
00626 }
00627 else
00628 {
00629 cout << "No rotation defined : only defined for TetrahedronFEMForceField !";
00630 return;
00631 }
00632
00633
00634
00635
00636
00637
00638 for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00639 {
00640 int sizeCurRowConst = constraints[curRowConst].size();
00641
00642
00643 for(int i = 0; i < sizeCurRowConst; i++)
00644 {
00645 const int localRowNodeIdx = constraints[curRowConst][i].index;
00646 Transformation Ri;
00647 forceField->getRotation(Ri, localRowNodeIdx);
00648 Ri.transpose();
00649
00650 const Deriv& n_i = Ri * constraints[curRowConst][i].data;
00651 constraints[curRowConst][i].data.x() = n_i.x();
00652 constraints[curRowConst][i].data.y() = n_i.y();
00653 constraints[curRowConst][i].data.z() = n_i.z();
00654 }
00655
00656
00657
00658
00659
00660
00661
00662
00663 }
00664 }
00665
00666
00667 template<>
00668 void PrecomputedConstraintCorrection<defaulttype::Rigid3dTypes>::rotateConstraints()
00669 {
00670 VecCoord& x = *mstate->getX();
00671 VecConst& constraints = *mstate->getC();
00672 VecCoord& x0 = *mstate->getX0();
00673
00674 unsigned int numConstraints = constraints.size();
00675
00676
00677
00678 for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00679 {
00680 int sizeCurRowConst = constraints[curRowConst].size();
00681
00682 for(int i = 0; i < sizeCurRowConst; i++)
00683 {
00684 const int localRowNodeIdx = constraints[curRowConst][i].index;
00685 Quat q;
00686 if (_restRotations)
00687 q = x[localRowNodeIdx].getOrientation() * x0[localRowNodeIdx].getOrientation().inverse();
00688 else
00689 q = x[localRowNodeIdx].getOrientation();
00690
00691
00692 Vec3d n_i = q.inverseRotate(constraints[curRowConst][i].data.getVCenter());
00693 Vec3d wn_i= q.inverseRotate(constraints[curRowConst][i].data.getVOrientation());
00694
00695
00696 constraints[curRowConst][i].data.getVCenter() = n_i;
00697 constraints[curRowConst][i].data.getVOrientation() = wn_i;
00698
00699 }
00700 }
00701 }
00702
00703
00704
00705 template<>
00706 void PrecomputedConstraintCorrection<defaulttype::Vec1dTypes>::rotateConstraints()
00707 {
00708 }
00709
00710
00711 template<>
00712 void PrecomputedConstraintCorrection<defaulttype::Vec3dTypes>::rotateResponse(){
00713 simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00714
00715 sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes>* forceField = NULL;
00716 if (node != NULL)
00717 {
00718
00719 forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3dTypes> > ();
00720 }
00721 else
00722 {
00723 cout << "No rotation defined !";
00724 return;
00725 }
00726 VecDeriv& dx = *mstate->getDx();
00727 for(unsigned int j = 0; j < dx.size(); j++)
00728 {
00729 Transformation Rj;
00730 forceField->getRotation(Rj, j);
00731
00732 const Deriv& toto = Rj * dx[j];
00733 dx[j] = toto;
00734 }
00735 }
00736
00737
00738
00739 template<>
00740 void PrecomputedConstraintCorrection<defaulttype::Rigid3dTypes>::rotateResponse(){
00741
00742 VecDeriv& dx = *mstate->getDx();
00743 VecCoord& x = *mstate->getX();
00744 VecCoord& x0 = *mstate->getX0();
00745 for(unsigned int j = 0; j < dx.size(); j++)
00746 {
00747
00748 Deriv toto ;
00749 Quat q;
00750 if (_restRotations)
00751 q = x[j].getOrientation() * x0[j].getOrientation().inverse();
00752 else
00753 q = x[j].getOrientation();
00754
00755 toto.getVCenter() = q.rotate(dx[j].getVCenter());
00756 toto.getVOrientation() = q.rotate(dx[j].getVOrientation());
00757 dx[j] = toto;
00758 }
00759 }
00760
00761 template<>
00762 void PrecomputedConstraintCorrection<defaulttype::Vec1dTypes>::rotateResponse()
00763 {
00764 }
00765 #endif
00766 #ifndef SOFA_DOUBLE
00767 template<>
00768 void PrecomputedConstraintCorrection<defaulttype::Vec3fTypes>::rotateConstraints()
00769 {
00770 VecConst& constraints = *mstate->getC();
00771 unsigned int numConstraints = constraints.size();
00772
00773 simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00774
00775 sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes>* forceField = NULL;
00776 if (node != NULL)
00777 {
00778
00779 forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes> > ();
00780 }
00781 else
00782 {
00783 cout << "No rotation defined : only defined for TetrahedronFEMForceField !";
00784 return;
00785 }
00786
00787
00788
00789
00790
00791
00792 for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00793 {
00794 int sizeCurRowConst = constraints[curRowConst].size();
00795
00796
00797 for(int i = 0; i < sizeCurRowConst; i++)
00798 {
00799 const int localRowNodeIdx = constraints[curRowConst][i].index;
00800 Transformation Ri;
00801 forceField->getRotation(Ri, localRowNodeIdx);
00802 Ri.transpose();
00803
00804 const Deriv& n_i = Ri * constraints[curRowConst][i].data;
00805 constraints[curRowConst][i].data.x() = n_i.x();
00806 constraints[curRowConst][i].data.y() = n_i.y();
00807 constraints[curRowConst][i].data.z() = n_i.z();
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817 }
00818 }
00819
00820 template<>
00821 void PrecomputedConstraintCorrection<defaulttype::Rigid3fTypes>::rotateConstraints()
00822 {
00823 VecCoord& x = *mstate->getX();
00824 VecConst& constraints = *mstate->getC();
00825 VecCoord& x0 = *mstate->getX0();
00826
00827 unsigned int numConstraints = constraints.size();
00828
00829
00830
00831 for(unsigned int curRowConst = 0; curRowConst < numConstraints; curRowConst++)
00832 {
00833 int sizeCurRowConst = constraints[curRowConst].size();
00834
00835 for(int i = 0; i < sizeCurRowConst; i++)
00836 {
00837 const int localRowNodeIdx = constraints[curRowConst][i].index;
00838 Quat q;
00839 if (_restRotations)
00840 q = x[localRowNodeIdx].getOrientation() * x0[localRowNodeIdx].getOrientation().inverse();
00841 else
00842 q = x[localRowNodeIdx].getOrientation();
00843
00844
00845 Vec3d n_i = q.inverseRotate(constraints[curRowConst][i].data.getVCenter());
00846 Vec3d wn_i= q.inverseRotate(constraints[curRowConst][i].data.getVOrientation());
00847
00848
00849 constraints[curRowConst][i].data.getVCenter() = n_i;
00850 constraints[curRowConst][i].data.getVOrientation() = wn_i;
00851
00852 }
00853 }
00854 }
00855
00856 template<>
00857 void PrecomputedConstraintCorrection<defaulttype::Vec1fTypes>::rotateConstraints()
00858 {
00859 }
00860
00861
00862 template<>
00863 void PrecomputedConstraintCorrection<defaulttype::Vec3fTypes>::rotateResponse(){
00864 simulation::tree::GNode *node = dynamic_cast<simulation::tree::GNode *>(getContext());
00865
00866 sofa::component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes>* forceField = NULL;
00867 if (node != NULL)
00868 {
00869
00870 forceField = node->get<component::forcefield::TetrahedronFEMForceField<defaulttype::Vec3fTypes> > ();
00871 }
00872 else
00873 {
00874 cout << "No rotation defined !";
00875 return;
00876 }
00877 VecDeriv& dx = *mstate->getDx();
00878 for(unsigned int j = 0; j < dx.size(); j++)
00879 {
00880 Transformation Rj;
00881 forceField->getRotation(Rj, j);
00882
00883 const Deriv& toto = Rj * dx[j];
00884 dx[j] = toto;
00885 }
00886 }
00887
00888
00889 template<>
00890 void PrecomputedConstraintCorrection<defaulttype::Rigid3fTypes>::rotateResponse(){
00891
00892 VecDeriv& dx = *mstate->getDx();
00893 VecCoord& x = *mstate->getX();
00894 VecCoord& x0 = *mstate->getX0();
00895 for(unsigned int j = 0; j < dx.size(); j++)
00896 {
00897
00898 Deriv toto ;
00899 Quat q;
00900 if (_restRotations)
00901 q = x[j].getOrientation() * x0[j].getOrientation().inverse();
00902 else
00903 q = x[j].getOrientation();
00904
00905 toto.getVCenter() = q.rotate(dx[j].getVCenter());
00906 toto.getVOrientation() = q.rotate(dx[j].getVOrientation());
00907 dx[j] = toto;
00908 }
00909 }
00910
00911 template<>
00912 void PrecomputedConstraintCorrection<defaulttype::Vec1fTypes>::rotateResponse()
00913 {
00914 }
00915
00916 #endif
00917
00918
00919
00920 }
00921
00922 }
00923
00924 }
00925
00926 #endif