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
00029
00030
00031
00032
00033
00034
00035 #include "PMLRigidBody.h"
00036
00037 #include <PhysicalModel.h>
00038 #include <CellProperties.h>
00039
00040 #include <sofa/defaulttype/Vec3Types.h>
00041 #include <sofa/component/mapping/RigidMapping.h>
00042 #include <sofa/component/mapping/IdentityMapping.h>
00043
00044 #include <sofa/component/mass/UniformMass.h>
00045 #include <sofa/component/mass/DiagonalMass.h>
00046 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00047 #include <sofa/component/topology/MeshTopology.h>
00048 #include <sofa/component/collision/TriangleModel.h>
00049
00050
00051
00052 using namespace sofa::component;
00053 using namespace sofa::component::mapping;
00054 using namespace sofa::component::collision;
00055 using namespace sofa::component::mass;
00056 using namespace sofa::component::topology;
00057
00058
00059
00060 namespace sofa
00061 {
00062
00063 namespace filemanager
00064 {
00065
00066 namespace pml
00067 {
00068
00069 PMLRigidBody::PMLRigidBody(StructuralComponent* body, GNode * parent)
00070 {
00071 parentNode = parent;
00072 bodyFixed = false;
00073
00074 collisionsON = body->getProperties()->getBool("collision");
00075 name = body->getProperties()->getName();
00076
00077 if(body->getProperties()->getString("mass") != "")
00078 initMass(body->getProperties()->getString("mass"));
00079
00080 if(body->getProperties()->getString("inertiaMatrix") != "")
00081 initInertiaMatrix(body->getProperties()->getString("inertiaMatrix"));
00082
00083 initPosition(body->getProperties()->getString("position"));
00084 initVelocity(body->getProperties()->getString("velocity"));
00085 solverName = body->getProperties()->getString("solver");
00086
00087
00088 createMass(body);
00089 createMechanicalState(body);
00090 createVisualModel(body);
00091 createCollisionModel();
00092 createSolver();
00093 }
00094
00095
00096 PMLRigidBody::~PMLRigidBody()
00097 {
00098 if(mmodel){ delete mmodel; mmodel=NULL;}
00099 if (mapping){ delete mapping; mapping = NULL;}
00100 if (VisualNode){ delete VisualNode; VisualNode = NULL;}
00101 if (CollisionNode){ delete CollisionNode; CollisionNode = NULL;}
00102 }
00103
00104
00105 void PMLRigidBody::initMass(string m)
00106 {
00107 int pos;
00108 while(!m.empty()) {
00109 pos = m.find(' ', 0);
00110 if(pos != 0) {
00111 string s=m.substr(0,pos);
00112 SReal d=atof(s.c_str());
00113 massList.push_back(d);
00114 m.erase(0,pos);
00115 }else
00116 m.erase(0,1);
00117 }
00118 }
00119
00120 void PMLRigidBody::initInertiaMatrix(string m)
00121 {
00122 int pos;
00123 while(!m.empty()) {
00124 pos = m.find(' ', 0);
00125 if(pos != 0) {
00126 string s=m.substr(0,pos);
00127 SReal d=atof(s.c_str());
00128 inertiaMatrix.push_back(d);
00129 m.erase(0,pos);
00130 }else
00131 m.erase(0,1);
00132 }
00133 }
00134
00135 void PMLRigidBody::initPosition(string m)
00136 {
00137 int pos;
00138 std::vector<SReal> vec;
00139 while(!m.empty()) {
00140 pos = m.find(' ', 0);
00141 if(pos != 0) {
00142 string s=m.substr(0,pos);
00143 SReal d=atof(s.c_str());
00144 vec.push_back(d);
00145 m.erase(0,pos);
00146 }else
00147 m.erase(0,1);
00148 }
00149 if (vec.size() >= 3)
00150 transPos = Vector3(vec[0],vec[1],vec[2]);
00151 else
00152 transPos = Vector3(0,0,0);
00153
00154 if (vec.size() == 6){
00155 rotPos = Quat(Vector3(1,0,0),vec[3]);
00156 rotPos += Quat(Vector3(0,1,0),vec[4]);
00157 rotPos += Quat(Vector3(0,0,1),vec[5]);
00158 }
00159 else if (vec.size() == 7)
00160 rotPos = Quat(vec[3], vec[4], vec[5], vec[6]);
00161 else {
00162 rotPos = Quat(Vector3(1,0,0),0);
00163 rotPos += Quat(Vector3(0,1,0),0);
00164 rotPos += Quat(Vector3(0,0,1),0);
00165 }
00166 }
00167
00168 void PMLRigidBody::initVelocity(string m)
00169 {
00170 int pos;
00171 std::vector<SReal> vec;
00172 while(!m.empty()) {
00173 pos = m.find(' ', 0);
00174 if(pos != 0) {
00175 string s=m.substr(0,pos);
00176 SReal d=atof(s.c_str());
00177 vec.push_back(d);
00178 m.erase(0,pos);
00179 }else
00180 m.erase(0,1);
00181 }
00182 if (vec.size() >= 3)
00183 transVel = Vector3(vec[0],vec[1],vec[2]);
00184 else
00185 transVel = Vector3(0,0,0);
00186
00187 if (vec.size() == 6)
00188 rotVel += Vector3(vec[3],vec[4],vec[5]);
00189 else
00190 rotVel = Vector3(0,0,0);
00191 }
00192
00193
00194 Vector3 PMLRigidBody::getDOF(unsigned int index)
00195 {
00196 return (*((MechanicalState<Vec3Types>*)mmodel)->getX())[index];
00197 }
00198
00199
00200 void PMLRigidBody::createMechanicalState(StructuralComponent* )
00201 {
00202 refDOF = new MechanicalObject<RigidTypes>;
00203 refDOF->resize(1);
00204
00205
00206 (*((MechanicalState<RigidTypes>*)refDOF)->getX())[0] = RigidTypes::Coord(transPos+bary, rotPos);
00207
00208
00209 (*((MechanicalState<RigidTypes>*)refDOF)->getV())[0] = RigidTypes::Deriv(transVel, rotVel);
00210
00211 parentNode->addObject(refDOF);
00212 }
00213
00214
00215 void PMLRigidBody::createTopology(StructuralComponent* body)
00216 {
00217
00218 unsigned int nbCells = body->getNumberOfCells();
00219
00220
00221
00222 if (nbCells == 1 && body->getCell(0)->getProperties()->getType() == StructureProperties::POLY_VERTEX )
00223 return;
00224
00225 topology = new MeshTopology();
00226 ((BaseMeshTopology*)topology)->clear();
00227
00228 BaseMeshTopology::Triangle * tri;
00229 BaseMeshTopology::Quad * quad;
00230 Cell * pCell;
00231 Atom * pAtom;
00232
00233
00234 for (unsigned int cid(0) ; cid<nbCells ; cid++) {
00235 pCell = body->getCell(cid);
00236 switch(pCell->getProperties()->getType()) {
00237
00238 case StructureProperties::TRIANGLE :
00239 tri = new BaseMeshTopology::Triangle;
00240 for (unsigned int p(0) ; p<3 ; p++) {
00241 pAtom = (Atom*)(pCell->getStructure(p));
00242 (*tri)[p] = AtomsToDOFsIndexes[pAtom->getIndex()];
00243 }
00244 ((BaseMeshTopology::SeqTriangles&)((BaseMeshTopology*)topology)->getTriangles()).push_back(*tri);
00245 break;
00246
00247 case StructureProperties::QUAD :
00248 quad = new BaseMeshTopology::Quad;
00249 for (unsigned int p(0) ; p<4 ; p++) {
00250 pAtom = (Atom*)(pCell->getStructure(p));
00251 (*quad)[p] = AtomsToDOFsIndexes[pAtom->getIndex()];
00252 }
00253 ((BaseMeshTopology::SeqQuads&)((BaseMeshTopology*)topology)->getQuads()).push_back(*quad);
00254 break;
00255
00256 default : break;
00257 }
00258 }
00259 }
00260
00261
00262 void PMLRigidBody::createVisualModel(StructuralComponent* body)
00263 {
00264 VisualNode = new GNode("points");
00265 parentNode->addChild(VisualNode);
00266
00267 mmodel = new MechanicalObject<Vec3Types>;
00268
00269 OglModel * vmodel = new OglModel;
00270 StructuralComponent* atoms = body->getAtoms();
00271 mmodel->resize(atoms->getNumberOfStructures());
00272 Atom* pAtom;
00273
00274 SReal pos[3];
00275 for (unsigned int i(0) ; i<atoms->getNumberOfStructures() ; i++) {
00276 pAtom = (Atom*) (atoms->getStructure(i));
00277 pAtom->getPosition(pos);
00278 AtomsToDOFsIndexes.insert(std::pair <unsigned int, unsigned int>(pAtom->getIndex(),i));
00279 (*((MechanicalState<Vec3Types>*)mmodel)->getX())[i] = Vector3(pos[0]-bary[0],pos[1]-bary[1],pos[2]-bary[2]);
00280 }
00281
00282 VisualNode->addObject(mmodel);
00283
00284 createTopology(body);
00285 VisualNode->addObject(topology);
00286
00287 double * color = body->getColor();
00288 vmodel->setColor((float)color[0], (float)color[1], (float)color[2], (float)color[3]);
00289 vmodel->load("","","");
00290
00291
00292 mapping = new RigidMapping< MechanicalMapping<MechanicalState<RigidTypes>, MechanicalState<Vec3Types> > >( (MechanicalState<RigidTypes>*)refDOF, (MechanicalState<Vec3Types>*)mmodel);
00293 BaseMapping * Vmapping = new IdentityMapping< Mapping< State<Vec3Types>, MappedModel< ExtVectorTypes< Vec<3,GLfloat>, Vec<3,GLfloat> > > > >((MechanicalState<Vec3Types>*)mmodel, vmodel);
00294
00295 VisualNode->addObject(mapping);
00296 VisualNode->addObject(Vmapping);
00297 VisualNode->addObject(vmodel);
00298
00299 }
00300
00301
00302 void PMLRigidBody::createMass(StructuralComponent* body)
00303 {
00304 if (! massList.empty())
00305 {
00306 StructuralComponent* atoms = body->getAtoms();
00307 Atom * pAtom;
00308 SReal masse = massList[0], totalMass=0.0;
00309 SReal pos[3];
00310 unsigned int nbPoints = atoms->getNumberOfStructures();
00311 SReal A,B,C,D,E,F;
00312 A = B = C = D = E = F = 0.0;
00313 bary[0] = bary[1] = bary[2] = 0.0;
00314
00315
00316 for (unsigned int i=0; i<nbPoints; i++)
00317 {
00318 if (massList.size() == nbPoints)
00319 masse = massList[i];
00320 pAtom = (Atom*)(atoms->getStructure(i));
00321 pAtom->getPosition(pos);
00322
00323
00324 A += masse * ( pos[1]*pos[1] + pos[2]*pos[2] );
00325 B += masse * ( pos[0]*pos[0] + pos[2]*pos[2] );
00326 C += masse * ( pos[0]*pos[0] + pos[1]*pos[1] );
00327 D += masse * pos[1] * pos[2];
00328 E += masse * pos[2] * pos[0];
00329 F += masse * pos[0] * pos[1];
00330 bary[0]+=pos[0]*masse; bary[1]+=pos[1]*masse; bary[2]+=pos[2]*masse;
00331 totalMass += masse;
00332 }
00333
00334
00335 bary[0]/=totalMass; bary[1]/=totalMass; bary[2]/=totalMass;
00336
00337 A += totalMass*(bary[1]*bary[1] + bary[2]*bary[2] );
00338 B += totalMass*(bary[2]*bary[2] + bary[0]*bary[0] );
00339 C += totalMass*(bary[0]*bary[0] + bary[1]*bary[1] );
00340 D -= totalMass* bary[1]*bary[2];
00341 E -= totalMass* bary[2]*bary[0];
00342 F -= totalMass* bary[0]*bary[1];
00343
00344 SReal coefs[9] = {A,-F, -E, -F, B, -D, -E, -D, C };
00345
00346 Mat3x3d iMatrix(coefs);
00347
00348
00349 if (massList.size() ==1) {
00350 mass = new UniformMass<Rigid3Types,Rigid3Mass>;
00351 Rigid3Mass m(masse);
00352 m.inertiaMatrix = iMatrix;
00353 ((UniformMass<Rigid3Types,Rigid3Mass>*)mass)->setMass( m );
00354 }else {
00355 mass = new DiagonalMass<Rigid3Types,Rigid3Mass>;
00356 for (unsigned int j=0 ; j<massList.size(); j++) {
00357 Rigid3Mass m(massList[j]);
00358 m.inertiaMatrix = iMatrix;
00359 ((DiagonalMass<Rigid3Types,Rigid3Mass>*)mass)->addMass( m );
00360 }
00361 }
00362 }
00363 else
00364 {
00365 Mat3x3d iMatrix;
00366 switch (inertiaMatrix.size())
00367 {
00368 case 0 :
00369 return;
00370 case 1 :
00371 {
00372 SReal val1 = inertiaMatrix[0];
00373 SReal coefs1[9] = {val1,0,0, 0,val1,0, 0,0,val1 };
00374 iMatrix = Mat3x3d(coefs1);
00375 break;
00376 }
00377 case 3 :
00378 {
00379 SReal coefs3[9] = {inertiaMatrix[0],0,0, 0,inertiaMatrix[1],0, 0,0,inertiaMatrix[2] };
00380 iMatrix = Mat3x3d(coefs3);
00381 break;
00382 }
00383 case 6 :
00384 {
00385 SReal coefs9[9] = {inertiaMatrix[0],inertiaMatrix[1],inertiaMatrix[2], \
00386 inertiaMatrix[1],inertiaMatrix[3],inertiaMatrix[4], \
00387 inertiaMatrix[2],inertiaMatrix[4],inertiaMatrix[5] };
00388 iMatrix = Mat3x3d(coefs9);
00389 break;
00390 }
00391 default :
00392 cerr<<"WARNING building "<<name<<" object : inertia matrix not properly defined."<<endl;
00393 return;
00394 }
00395 mass = new UniformMass<Rigid3Types,Rigid3Mass>;
00396 Rigid3Mass m(1.0);
00397 m.inertiaMatrix = iMatrix;
00398 ((UniformMass<Rigid3Types,Rigid3Mass>*)mass)->setMass( m );
00399 }
00400
00401 if (mass)
00402 parentNode->addObject(mass);
00403 }
00404
00405 void PMLRigidBody::createCollisionModel()
00406 {
00407 if (collisionsON)
00408 {
00409
00410
00411
00412
00413
00414
00415
00416 TriangleModel * cmodel = new TriangleModel;
00417
00418
00419 VisualNode->addObject(cmodel);
00420
00421
00422
00423 cmodel->init();
00424
00425
00426 }
00427 }
00428
00429
00430 bool PMLRigidBody::FusionBody(PMLBody* )
00431 {
00432 return false;
00433 }
00434
00435
00436 }
00437 }
00438 }