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_HEXAHEDRALFEMFORCEFIELD_INL
00026 #define SOFA_COMPONENT_FORCEFIELD_HEXAHEDRALFEMFORCEFIELD_INL
00027
00028 #include <sofa/core/componentmodel/behavior/ForceField.inl>
00029 #include <sofa/component/forcefield/HexahedralFEMForceField.h>
00030 #include <sofa/helper/PolarDecompose.h>
00031 #include <sofa/helper/gl/template.h>
00032 #include <assert.h>
00033 #include <iostream>
00034 #include <set>
00035
00036 #include <sofa/component/topology/HexahedronData.inl>
00037
00038 using std::cerr;
00039 using std::endl;
00040 using std::set;
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058 namespace sofa
00059 {
00060
00061 namespace component
00062 {
00063
00064 namespace forcefield
00065 {
00066
00067 using namespace sofa::defaulttype;
00068 using namespace sofa::component::topology;
00069 using namespace core::componentmodel::topology;
00070
00071 template< class DataTypes>
00072 void HexahedralFEMForceField<DataTypes>::FHexahedronCreationFunction (int hexahedronIndex, void* param,
00073 HexahedronInformation &,
00074 const Hexahedron& ,
00075 const helper::vector< unsigned int > &,
00076 const helper::vector< double >&)
00077 {
00078 HexahedralFEMForceField<DataTypes> *ff= (HexahedralFEMForceField<DataTypes> *)param;
00079 if (ff) {
00080
00081 switch(ff->method)
00082 {
00083 case LARGE :
00084 ff->computeMaterialStiffness(hexahedronIndex);
00085 ff->initLarge(hexahedronIndex);
00086
00087 break;
00088 case POLAR :
00089 ff->computeMaterialStiffness(hexahedronIndex);
00090 ff->initPolar(hexahedronIndex);
00091 break;
00092 }
00093 }
00094 }
00095
00096 template<class DataTypes>
00097 void HexahedralFEMForceField<DataTypes>::parse(core::objectmodel::BaseObjectDescription* arg)
00098 {
00099 this->core::componentmodel::behavior::ForceField<DataTypes>::parse(arg);
00100
00101
00102 }
00103
00104 template <class DataTypes> void HexahedralFEMForceField<DataTypes>::handleTopologyChange()
00105 {
00106 std::list<const TopologyChange *>::const_iterator itBegin=_topology->firstChange();
00107 std::list<const TopologyChange *>::const_iterator itEnd=_topology->lastChange();
00108
00109
00110 hexahedronInfo.handleTopologyEvents(itBegin,itEnd);
00111
00112 }
00113
00114 template <class DataTypes>
00115 void HexahedralFEMForceField<DataTypes>::init()
00116 {
00117 if(_alreadyInit)return;
00118 else _alreadyInit=true;
00119
00120 this->core::componentmodel::behavior::ForceField<DataTypes>::init();
00121
00122 _topology = getContext()->getMeshTopology();
00123
00124 if (_topology->getNbHexas()==0)
00125 {
00126 std::cerr << "ERROR(HexahedralFEMForceField): object must have a Hexahedral Set Topology.\n";
00127 return;
00128 }
00129
00130
00131
00132
00133
00134
00135
00136
00137
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176 reinit();
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196 }
00197
00198
00199 template <class DataTypes>
00200 void HexahedralFEMForceField<DataTypes>::reinit()
00201 {
00202 if (f_method.getValue() == "large")
00203 this->setMethod(LARGE);
00204 else if (f_method.getValue() == "polar")
00205 this->setMethod(POLAR);
00206
00207 hexahedronInfo.resize(_topology->getNbHexas());
00208
00209 for (int i=0;i<_topology->getNbHexas();++i) {
00210 FHexahedronCreationFunction(i, (void*) this, hexahedronInfo[i],
00211 _topology->getHexa(i), (const std::vector< unsigned int > )0,
00212 (const std::vector< double >)0);
00213 }
00214
00215 hexahedronInfo.setCreateFunction(FHexahedronCreationFunction);
00216 hexahedronInfo.setCreateParameter( (void *) this );
00217 hexahedronInfo.setDestroyParameter( (void *) this );
00218
00219 }
00220
00221
00222
00226
00227
00228
00229
00230 template<class DataTypes>
00231 void HexahedralFEMForceField<DataTypes>::addForce (VecDeriv& f, const VecCoord& p, const VecDeriv& )
00232 {
00233 f.resize(p.size());
00234
00235 switch(method)
00236 {
00237 case LARGE :
00238 {
00239 for(int i = 0 ; i<_topology->getNbHexas();++i)
00240 {
00241 accumulateForceLarge( f, p, i);
00242 }
00243 break;
00244 }
00245 case POLAR :
00246 {
00247 for(int i = 0 ; i<_topology->getNbHexas();++i)
00248 {
00249 accumulateForcePolar( f, p, i);
00250 }
00251 break;
00252 }
00253 }
00254
00255 }
00256
00257 template<class DataTypes>
00258 void HexahedralFEMForceField<DataTypes>::addDForce (VecDeriv& v, const VecDeriv& x)
00259 {
00260 if( v.size()!=x.size() ) v.resize(x.size());
00261
00262
00263
00264
00265 for(int i = 0 ; i<_topology->getNbHexas();++i)
00266 {
00267
00268 Transformation R_0_2;
00269 R_0_2.transpose(hexahedronInfo[i].rotation);
00270
00271 Displacement X;
00272
00273 for(int w=0;w<8;++w)
00274 {
00275 Coord x_2;
00276 x_2 = R_0_2 * x[_topology->getHexa(i)[w]];
00277 X[w*3] = x_2[0];
00278 X[w*3+1] = x_2[1];
00279 X[w*3+2] = x_2[2];
00280 }
00281
00282 Displacement F;
00283 computeForce( F, X, hexahedronInfo[i].stiffness );
00284
00285
00286 for(int w=0;w<8;++w)
00287 v[_topology->getHexa(i)[w]] -= hexahedronInfo[i].rotation * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00288 }
00289
00290 }
00291
00292 template <class DataTypes>
00293 double HexahedralFEMForceField<DataTypes>::getPotentialEnergy(const VecCoord&)
00294 {
00295 std::cerr<<"HexahedralFEMForceField::getPotentialEnergy-not-implemented !!!"<<std::endl;
00296 return 0;
00297 }
00298
00299
00300
00301
00302
00306
00307
00308
00309
00310
00311
00312 template<class DataTypes>
00313 void HexahedralFEMForceField<DataTypes>::computeElementStiffness( ElementStiffness &K, const MaterialStiffness &M, const Vec<8,Coord> &nodes, const int )
00314 {
00315 Mat33 J_1;
00316 J_1.fill( 0.0 );
00317 Coord l = nodes[6] - nodes[0];
00318 J_1[0][0]=2.0f / l[0];
00319 J_1[1][1]=2.0f / l[1];
00320 J_1[2][2]=2.0f / l[2];
00321
00322
00323 Real vol = ((nodes[1]-nodes[0]).norm()*(nodes[3]-nodes[0]).norm()*(nodes[4]-nodes[0]).norm());
00324 vol /= 8.0;
00325
00326 K.clear();
00327
00328
00329 for(int i=0;i<8;++i)
00330 {
00331 Mat33 k = vol*integrateStiffness( _coef[i][0], _coef[i][1],_coef[i][2], _coef[i][0], _coef[i][1],_coef[i][2], M[0][0], M[0][1],M[2][2], J_1 );
00332
00333
00334 for(int m=0;m<3;++m)
00335 for(int l=0;l<3;++l)
00336 {
00337 K[i*3+m][i*3+l] += k[m][l];
00338 }
00339
00340
00341
00342 for(int j=i+1;j<8;++j)
00343 {
00344 Mat33 k = vol*integrateStiffness( _coef[i][0], _coef[i][1],_coef[i][2], _coef[j][0], _coef[j][1],_coef[j][2], M[0][0], M[0][1],M[2][2], J_1 );
00345
00346
00347 for(int m=0;m<3;++m)
00348 for(int l=0;l<3;++l)
00349 {
00350 K[i*3+m][j*3+l] += k[m][l];
00351
00352 }
00353 }
00354 }
00355
00356 for(int i=0;i<24;++i)
00357 for(int j=i+1;j<24;++j)
00358 {
00359 K[j][i] = K[i][j];
00360 }
00361
00362
00363 }
00364
00365
00366
00367
00368 template<class DataTypes>
00369 typename HexahedralFEMForceField<DataTypes>::Mat33 HexahedralFEMForceField<DataTypes>::integrateStiffness( int signx0, int signy0, int signz0, int signx1, int signy1, int signz1, const Real u, const Real v, const Real w, const Mat33& J_1 )
00370 {
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447 Mat33 K;
00448
00449 Real t1 = J_1[0][0]*J_1[0][0];
00450 Real t2 = t1*signx0;
00451 Real t3 = (Real)(signy0*signz0);
00452 Real t4 = t2*t3;
00453 Real t5 = w*signx1;
00454 Real t6 = (Real)(signy1*signz1);
00455 Real t7 = t5*t6;
00456 Real t10 = t1*signy0;
00457 Real t12 = w*signy1;
00458 Real t13 = t12*signz1;
00459 Real t16 = t2*signz0;
00460 Real t17 = u*signx1;
00461 Real t18 = t17*signz1;
00462 Real t21 = t17*t6;
00463 Real t24 = t2*signy0;
00464 Real t25 = t17*signy1;
00465 Real t28 = t5*signy1;
00466 Real t32 = w*signz1;
00467 Real t37 = t5*signz1;
00468 Real t43 = J_1[0][0]*signx0;
00469 Real t45 = v*J_1[1][1];
00470 Real t49 = J_1[0][0]*signy0;
00471 Real t50 = t49*signz0;
00472 Real t51 = w*J_1[1][1];
00473 Real t52 = (Real)(signx1*signz1);
00474 Real t53 = t51*t52;
00475 Real t56 = t45*signy1;
00476 Real t64 = v*J_1[2][2];
00477 Real t68 = w*J_1[2][2];
00478 Real t69 = (Real)(signx1*signy1);
00479 Real t70 = t68*t69;
00480 Real t73 = t64*signz1;
00481 Real t81 = J_1[1][1]*signy0;
00482 Real t83 = v*J_1[0][0];
00483 Real t87 = J_1[1][1]*signx0;
00484 Real t88 = t87*signz0;
00485 Real t89 = w*J_1[0][0];
00486 Real t90 = t89*t6;
00487 Real t93 = t83*signx1;
00488 Real t100 = J_1[1][1]*J_1[1][1];
00489 Real t101 = t100*signx0;
00490 Real t102 = t101*t3;
00491 Real t110 = t100*signy0;
00492 Real t111 = t110*signz0;
00493 Real t112 = u*signy1;
00494 Real t113 = t112*signz1;
00495 Real t116 = t101*signy0;
00496 Real t144 = J_1[2][2]*signy0;
00497 Real t149 = J_1[2][2]*signx0;
00498 Real t150 = t149*signy0;
00499 Real t153 = J_1[2][2]*signz0;
00500 Real t172 = J_1[2][2]*J_1[2][2];
00501 Real t173 = t172*signx0;
00502 Real t174 = t173*t3;
00503 Real t177 = t173*signz0;
00504 Real t180 = t172*signy0;
00505 Real t181 = t180*signz0;
00506 K[0][0] = (float)(t4*t7/36.0+t10*signz0*t13/12.0+t16*t18/24.0+t4*t21/72.0+
00507 t24*t25/24.0+t24*t28/24.0+t1*signz0*t32/8.0+t10*t12/8.0+t16*t37/24.0+t2*t17/8.0);
00508 K[0][1] = (float)(t43*signz0*t45*t6/24.0+t50*t53/24.0+t43*t56/8.0+t49*t51*
00509 signx1/8.0);
00510 K[0][2] = (float)(t43*signy0*t64*t6/24.0+t50*t70/24.0+t43*t73/8.0+J_1[0][0]*signz0
00511 *t68*signx1/8.0);
00512 K[1][0] = (float)(t81*signz0*t83*t52/24.0+t88*t90/24.0+t81*t93/8.0+t87*t89*
00513 signy1/8.0);
00514 K[1][1] = (float)(t102*t7/36.0+t102*t21/72.0+t101*signz0*t37/12.0+t111*t113
00515 /24.0+t116*t28/24.0+t100*signz0*t32/8.0+t111*t13/24.0+t116*t25/24.0+t110*t112/
00516 8.0+t101*t5/8.0);
00517 K[1][2] = (float)(t87*signy0*t64*t52/24.0+t88*t70/24.0+t81*t73/8.0+J_1[1][1]*
00518 signz0*t68*signy1/8.0);
00519 K[2][0] = (float)(t144*signz0*t83*t69/24.0+t150*t90/24.0+t153*t93/8.0+t149*
00520 t89*signz1/8.0);
00521 K[2][1] = (float)(t149*signz0*t45*t69/24.0+t150*t53/24.0+t153*t56/8.0+t144*
00522 t51*signz1/8.0);
00523 K[2][2] = (float)(t174*t7/36.0+t177*t37/24.0+t181*t13/24.0+t174*t21/72.0+
00524 t173*signy0*t28/12.0+t180*t12/8.0+t181*t113/24.0+t177*t18/24.0+t172*signz0*u*
00525 signz1/8.0+t173*t5/8.0);
00526
00527 return K ;
00528
00529 }
00530
00531
00532
00533 template<class DataTypes>
00534 void HexahedralFEMForceField<DataTypes>::computeMaterialStiffness(int i)
00535 {
00536
00537
00538 hexahedronInfo[i].materialMatrix[0][0] = hexahedronInfo[i].materialMatrix[1][1] = hexahedronInfo[i].materialMatrix[2][2] = 1;
00539 hexahedronInfo[i].materialMatrix[0][1] = hexahedronInfo[i].materialMatrix[0][2] = hexahedronInfo[i].materialMatrix[1][0]
00540 = hexahedronInfo[i].materialMatrix[1][2] = hexahedronInfo[i].materialMatrix[2][0] =
00541 hexahedronInfo[i].materialMatrix[2][1] = f_poissonRatio.getValue()/(1-f_poissonRatio.getValue());
00542 hexahedronInfo[i].materialMatrix[0][3] = hexahedronInfo[i].materialMatrix[0][4] = hexahedronInfo[i].materialMatrix[0][5] = 0;
00543 hexahedronInfo[i].materialMatrix[1][3] = hexahedronInfo[i].materialMatrix[1][4] = hexahedronInfo[i].materialMatrix[1][5] = 0;
00544 hexahedronInfo[i].materialMatrix[2][3] = hexahedronInfo[i].materialMatrix[2][4] = hexahedronInfo[i].materialMatrix[2][5] = 0;
00545 hexahedronInfo[i].materialMatrix[3][0] = hexahedronInfo[i].materialMatrix[3][1] = hexahedronInfo[i].materialMatrix[3][2] = hexahedronInfo[i].materialMatrix[3][4] = hexahedronInfo[i].materialMatrix[3][5] = 0;
00546 hexahedronInfo[i].materialMatrix[4][0] = hexahedronInfo[i].materialMatrix[4][1] = hexahedronInfo[i].materialMatrix[4][2] = hexahedronInfo[i].materialMatrix[4][3] = hexahedronInfo[i].materialMatrix[4][5] = 0;
00547 hexahedronInfo[i].materialMatrix[5][0] = hexahedronInfo[i].materialMatrix[5][1] = hexahedronInfo[i].materialMatrix[5][2] = hexahedronInfo[i].materialMatrix[5][3] = hexahedronInfo[i].materialMatrix[5][4] = 0;
00548 hexahedronInfo[i].materialMatrix[3][3] = hexahedronInfo[i].materialMatrix[4][4] = hexahedronInfo[i].materialMatrix[5][5] = (1-2*f_poissonRatio.getValue())/(2*(1-f_poissonRatio.getValue()));
00549 hexahedronInfo[i].materialMatrix *= (f_youngModulus.getValue()*(1-f_poissonRatio.getValue()))/((1+f_poissonRatio.getValue())*(1-2*f_poissonRatio.getValue()));
00550 }
00551
00552 template<class DataTypes>
00553 void HexahedralFEMForceField<DataTypes>::computeForce( Displacement &F, const Displacement &Depl, const ElementStiffness &K )
00554 {
00555 F = K*Depl;
00556 }
00557
00558
00559
00560
00561
00562
00563
00564
00565
00570
00571
00572 template<class DataTypes>
00573 void HexahedralFEMForceField<DataTypes>::initLarge(int i)
00574 {
00575
00576
00577
00578
00579
00580 const VecCoord *X0=this->mstate->getX0();
00581
00582 Vec<8,Coord> nodes;
00583 for(int w=0;w<8;++w)
00584 nodes[w] = (*X0)[_topology->getHexa(i)[w]];
00585
00586
00587 Coord horizontal;
00588 horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00589 Coord vertical;
00590 vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00591 Transformation R_0_1;
00592 computeRotationLarge( R_0_1, horizontal,vertical);
00593
00594 for(int w=0;w<8;++w)
00595 hexahedronInfo[i].rotatedInitialElements[w] = R_0_1*(*X0)[_topology->getHexa(i)[w]];
00596
00597
00598 computeElementStiffness( hexahedronInfo[i].stiffness, hexahedronInfo[i].materialMatrix, nodes, i );
00599
00600
00601
00602 }
00603
00604 template<class DataTypes>
00605 void HexahedralFEMForceField<DataTypes>::computeRotationLarge( Transformation &r, Coord &edgex, Coord &edgey)
00606 {
00607
00608
00609
00610 edgex.normalize();
00611 edgey.normalize();
00612
00613 Coord edgez = cross( edgex, edgey );
00614 edgez.normalize();
00615
00616 edgey = cross( edgez, edgex );
00617 edgey.normalize();
00618
00619 r[0][0] = edgex[0];
00620 r[0][1] = edgex[1];
00621 r[0][2] = edgex[2];
00622 r[1][0] = edgey[0];
00623 r[1][1] = edgey[1];
00624 r[1][2] = edgey[2];
00625 r[2][0] = edgez[0];
00626 r[2][1] = edgez[1];
00627 r[2][2] = edgez[2];
00628
00629
00630
00631
00632
00633
00634
00635
00636
00637
00638
00639 }
00640
00641 template<class DataTypes>
00642 void HexahedralFEMForceField<DataTypes>::accumulateForceLarge( Vector& f, const Vector & p, int i)
00643 {
00644 Vec<8,Coord> nodes;
00645 for(int w=0;w<8;++w)
00646 nodes[w] = p[_topology->getHexa(i)[w]];
00647
00648 Coord horizontal;
00649 horizontal = (nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00650 Coord vertical;
00651 vertical = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00652
00653 Transformation R_0_2;
00654 computeRotationLarge( R_0_2, horizontal,vertical);
00655
00656 hexahedronInfo[i].rotation.transpose(R_0_2);
00657
00658
00659 Vec<8,Coord> deformed;
00660 for(int w=0;w<8;++w)
00661 deformed[w] = R_0_2 * nodes[w];
00662
00663
00664
00665 Displacement D;
00666 for(int k=0 ; k<8 ; ++k )
00667 {
00668 int indice = k*3;
00669 for(int j=0 ; j<3 ; ++j )
00670 D[indice+j] = hexahedronInfo[i].rotatedInitialElements[k][j] - deformed[k][j];
00671 }
00672
00673
00674
00675
00676
00677
00678 Displacement F;
00679 computeForce( F, D, hexahedronInfo[i].stiffness );
00680
00681 for(int w=0;w<8;++w)
00682 f[_topology->getHexa(i)[w]] += hexahedronInfo[i].rotation * Deriv( F[w*3], F[w*3+1], F[w*3+2] );
00683 }
00684
00685
00686
00687
00688
00689
00690
00695
00696
00697
00698 template<class DataTypes>
00699 void HexahedralFEMForceField<DataTypes>::initPolar(int i)
00700 {
00701 const VecCoord *X0=this->mstate->getX0();
00702
00703 Vec<8,Coord> nodes;
00704 for(int j=0;j<8;++j)
00705 nodes[j] = (*X0)[_topology->getHexa(i)[j]];
00706
00707 Transformation R_0_1;
00708 computeRotationPolar( R_0_1, nodes );
00709
00710
00711 for(int j=0;j<8;++j)
00712 {
00713 hexahedronInfo[i].rotatedInitialElements[j] = R_0_1 * nodes[j];
00714 }
00715
00716 computeElementStiffness( hexahedronInfo[i].stiffness, hexahedronInfo[i].materialMatrix, nodes, i );
00717
00718 }
00719
00720
00721
00722 template<class DataTypes>
00723 void HexahedralFEMForceField<DataTypes>::computeRotationPolar( Transformation &r, Vec<8,Coord> &nodes)
00724 {
00725 Transformation A;
00726 Coord Edge =(nodes[1]-nodes[0] + nodes[2]-nodes[3] + nodes[5]-nodes[4] + nodes[6]-nodes[7])*.25;
00727 A[0][0] = Edge[0];
00728 A[0][1] = Edge[1];
00729 A[0][2] = Edge[2];
00730 Edge = (nodes[3]-nodes[0] + nodes[2]-nodes[1] + nodes[7]-nodes[4] + nodes[6]-nodes[5])*.25;
00731 A[1][0] = Edge[0];
00732 A[1][1] = Edge[1];
00733 A[1][2] = Edge[2];
00734 Edge = (nodes[4]-nodes[0] + nodes[5]-nodes[1] + nodes[7]-nodes[3] + nodes[6]-nodes[2])*.25;
00735 A[2][0] = Edge[0];
00736 A[2][1] = Edge[1];
00737 A[2][2] = Edge[2];
00738
00739 Mat33 HT;
00740 for(int k=0;k<3;++k)
00741 for(int j=0;j<3;++j)
00742 HT[k][j]=A[k][j];
00743
00744
00745 Mat33 S;
00746
00747 polar_decomp(HT, r, S);
00748 }
00749
00750
00751 template<class DataTypes>
00752 void HexahedralFEMForceField<DataTypes>::accumulateForcePolar( Vector& f, const Vector & p, int i)
00753 {
00754 Vec<8,Coord> nodes;
00755 for(int j=0;j<8;++j)
00756 nodes[j] = p[_topology->getHexa(i)[j]];
00757
00758
00759 Transformation R_0_2;
00760 computeRotationPolar( R_0_2, nodes );
00761
00762 hexahedronInfo[i].rotation.transpose( R_0_2 );
00763
00764
00765
00766 Vec<8,Coord> deformed;
00767 for(int j=0;j<8;++j)
00768 deformed[j] = R_0_2 * nodes[j];
00769
00770
00771
00772
00773 Displacement D;
00774 for(int k=0 ; k<8 ; ++k )
00775 {
00776 int indice = k*3;
00777 for(int j=0 ; j<3 ; ++j )
00778 D[indice+j] = hexahedronInfo[i].rotatedInitialElements[k][j] - deformed[k][j];
00779 }
00780
00781
00782 Displacement F;
00783
00784
00785
00786
00787
00788 computeForce( F, D, hexahedronInfo[i].stiffness );
00789
00790
00791 for(int j=0;j<8;++j)
00792 f[_topology->getHexa(i)[j]] += hexahedronInfo[i].rotation * Deriv( F[j*3], F[j*3+1], F[j*3+2] );
00793 }
00794
00795
00796
00797
00798
00799
00803
00804
00805
00806
00807
00808 template<class DataTypes>
00809 void HexahedralFEMForceField<DataTypes>::draw()
00810 {
00811
00812 if (!getContext()->getShowForceFields()) return;
00813 if (!this->mstate) return;
00814
00815
00816 const VecCoord& x = *this->mstate->getX();
00817
00818 if (getContext()->getShowWireFrame())
00819 glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00820
00821 glDisable(GL_LIGHTING);
00822
00823
00824
00825
00826
00827 for(int i = 0 ; i<_topology->getNbHexas();++i)
00828 {
00829
00830 const Hexahedron &t=_topology->getHexa(i);
00831
00832 Index a = t[0];
00833 Index b = t[1];
00834 Index d = t[2];
00835 Index c = t[3];
00836 Index e = t[4];
00837 Index f = t[5];
00838 Index h = t[6];
00839 Index g = t[7];
00840
00841
00842
00843
00844
00845
00846
00847
00848
00849
00850
00851
00852 Coord center = (x[a]+x[b]+x[c]+x[d]+x[e]+x[g]+x[f]+x[h])*0.125;
00853 Real percentage = (Real) 0.15;
00854 Coord p0 = x[a]-(x[a]-center)*percentage;
00855 Coord p1 = x[b]-(x[b]-center)*percentage;
00856 Coord p2 = x[c]-(x[c]-center)*percentage;
00857 Coord p3 = x[d]-(x[d]-center)*percentage;
00858 Coord p4 = x[e]-(x[e]-center)*percentage;
00859 Coord p5 = x[f]-(x[f]-center)*percentage;
00860 Coord p6 = x[g]-(x[g]-center)*percentage;
00861 Coord p7 = x[h]-(x[h]-center)*percentage;
00862
00863
00864
00865
00866
00867 glColor4f(0.7f, 0.7f, 0.1f, (1.0f));
00868 glBegin(GL_QUADS);
00869 helper::gl::glVertexT(p5);
00870 helper::gl::glVertexT(p1);
00871 helper::gl::glVertexT(p3);
00872 helper::gl::glVertexT(p7);
00873
00874 glColor4f(0.7f, 0, 0, (1.0f));
00875
00876 helper::gl::glVertexT(p1);
00877 helper::gl::glVertexT(p0);
00878 helper::gl::glVertexT(p2);
00879 helper::gl::glVertexT(p3);
00880
00881 glColor4f(0, 0.7f, 0, (1.0f));
00882
00883 helper::gl::glVertexT(p0);
00884 helper::gl::glVertexT(p4);
00885 helper::gl::glVertexT(p6);
00886 helper::gl::glVertexT(p2);
00887
00888 glColor4f(0, 0, 0.7f, (1.0f));
00889
00890 helper::gl::glVertexT(p4);
00891 helper::gl::glVertexT(p5);
00892 helper::gl::glVertexT(p7);
00893 helper::gl::glVertexT(p6);
00894
00895 glColor4f(0.1f, 0.7f, 0.7f, (1.0f));
00896
00897 helper::gl::glVertexT(p7);
00898 helper::gl::glVertexT(p3);
00899 helper::gl::glVertexT(p2);
00900 helper::gl::glVertexT(p6);
00901
00902 glColor4f(0.7f, 0.1f, 0.7f, (1.0f));
00903
00904 helper::gl::glVertexT(p1);
00905 helper::gl::glVertexT(p5);
00906 helper::gl::glVertexT(p4);
00907 helper::gl::glVertexT(p0);
00908 glEnd();
00909 }
00910
00911 if (getContext()->getShowWireFrame())
00912 glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00913
00914 }
00915
00916 }
00917
00918 }
00919
00920 }
00921
00922 #endif