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_COLLISION_BARYCENTRICCONTACTMAPPER_H
00026 #define SOFA_COMPONENT_COLLISION_BARYCENTRICCONTACTMAPPER_H
00027
00028 #include <sofa/helper/system/config.h>
00029 #include <sofa/helper/Factory.h>
00030 #include <sofa/component/mapping/BarycentricMapping.h>
00031 #include <sofa/component/mapping/IdentityMapping.h>
00032 #include <sofa/component/mapping/RigidMapping.h>
00033 #include <sofa/component/mapping/SubsetMapping.h>
00034 #include <sofa/component/MechanicalObject.h>
00035 #include <sofa/simulation/tree/GNode.h>
00036 #include <sofa/simulation/tree/Simulation.h>
00037 #include <sofa/component/collision/SphereModel.h>
00038 #include <sofa/component/collision/SphereTreeModel.h>
00039 #include <sofa/component/collision/TriangleModel.h>
00040 #include <sofa/component/collision/TetrahedronModel.h>
00041 #include <sofa/component/collision/LineModel.h>
00042 #include <sofa/component/collision/PointModel.h>
00043 #include <sofa/component/collision/DistanceGridCollisionModel.h>
00044 #include <sofa/component/mapping/IdentityMapping.h>
00045 #include <sofa/component/visualmodel/DrawV.h>
00046 #include <iostream>
00047
00048
00049 namespace sofa
00050 {
00051
00052 namespace component
00053 {
00054
00055 namespace collision
00056 {
00057
00058 using namespace sofa::defaulttype;
00059
00061 template < class TCollisionModel, class DataTypes = typename TCollisionModel::DataTypes >
00062 class ContactMapper;
00063
00065 template <class TDataTypes>
00066 class BaseContactMapper
00067 {
00068 public:
00069 typedef TDataTypes DataTypes;
00070 typedef typename DataTypes::Real Real;
00071 typedef typename DataTypes::Coord Coord;
00072 typedef typename DataTypes::VecCoord VecCoord;
00073 typedef core::componentmodel::behavior::MechanicalState<DataTypes> MMechanicalState;
00074 virtual ~BaseContactMapper() {}
00075 virtual MMechanicalState* createMapping(const char* name = "contactPoints") = 0;
00076 virtual void cleanup() = 0;
00077 virtual void resize(int size) = 0;
00078 virtual int addPoint(const Coord& c, int index, Real& r) = 0;
00079 virtual void update() = 0;
00080
00081 typedef helper::Factory< std::string, BaseContactMapper<DataTypes>, core::CollisionModel* > ContactMapperFactory;
00082 static BaseContactMapper<DataTypes>* Create(core::CollisionModel* model, const std::string& name = std::string("default"))
00083 {
00084 return ContactMapperFactory::CreateObject(name, model);
00085 }
00086
00087 template < class TCollisionModel>
00088 static void create( ContactMapper<TCollisionModel, DataTypes>*& obj, core::CollisionModel* arg)
00089 {
00090 TCollisionModel* model = dynamic_cast<TCollisionModel*>(arg);
00091 if (model == NULL) return;
00092 obj = new ContactMapper<TCollisionModel, DataTypes>;
00093 obj->setCollisionModel(model);
00094 }
00095
00096 };
00097
00099 template < class TCollisionModel, class DataTypes >
00100 class BarycentricContactMapper : public BaseContactMapper<DataTypes>
00101 {
00102 public:
00103 typedef typename DataTypes::Real Real;
00104 typedef typename DataTypes::Coord Coord;
00105 typedef TCollisionModel MCollisionModel;
00106 typedef typename MCollisionModel::InDataTypes InDataTypes;
00107 typedef typename MCollisionModel::Topology InTopology;
00108 typedef core::componentmodel::behavior::MechanicalState< InDataTypes> InMechanicalState;
00109 typedef core::componentmodel::behavior::MechanicalState< typename BarycentricContactMapper::DataTypes> MMechanicalState;
00110 typedef component::MechanicalObject<typename BarycentricContactMapper::DataTypes> MMechanicalObject;
00111 typedef mapping::BarycentricMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00112 typedef mapping::TopologyBarycentricMapper<InDataTypes, typename BarycentricContactMapper::DataTypes> MMapper;
00113 MCollisionModel* model;
00114 MMapping* mapping;
00115 MMapper* mapper;
00116
00117 BarycentricContactMapper()
00118 : model(NULL), mapping(NULL), mapper(NULL)
00119 {
00120 }
00121
00122 void setCollisionModel(MCollisionModel* model)
00123 {
00124 this->model = model;
00125 }
00126
00127 void cleanup();
00128
00129 MMechanicalState* createMapping(const char* name="contactPoints");
00130
00131 void resize(int size)
00132 {
00133 if (mapping!=NULL)
00134 {
00135 mapper->clear();
00136 mapping->getMechTo()->resize(size);
00137 }
00138 }
00139
00140 void update()
00141 {
00142 if (mapping!=NULL)
00143 {
00144 mapping->updateMapping();
00145 }
00146 }
00147 };
00148
00150 template<class DataTypes>
00151 class ContactMapper<LineModel, DataTypes> : public BarycentricContactMapper<LineModel, DataTypes>
00152 {
00153 public:
00154 typedef typename DataTypes::Real Real;
00155 typedef typename DataTypes::Coord Coord;
00156 int addPoint(const Coord& P, int index, Real&)
00157 {
00158 return this->mapper->createPointInLine(P, index, this->model->getMechanicalState()->getX());
00159 }
00160
00161 };
00162
00164 template<class DataTypes>
00165 class ContactMapper<TriangleModel, DataTypes> : public BarycentricContactMapper<TriangleModel, DataTypes>
00166 {
00167 public:
00168 typedef typename DataTypes::Real Real;
00169 typedef typename DataTypes::Coord Coord;
00170 int addPoint(const Coord& P, int index, Real&)
00171 {
00172 int nbt = this->model->getMeshTopology()->getNbTriangles();
00173 if (index < nbt)
00174 return this->mapper->createPointInTriangle(P, index, this->model->getMechanicalState()->getX());
00175 else
00176 {
00177 int qindex = (index - nbt)/2;
00178 int nbq = this->model->getMeshTopology()->getNbQuads();
00179 if (qindex < nbq)
00180 return this->mapper->createPointInQuad(P, qindex, this->model->getMechanicalState()->getX());
00181 else
00182 {
00183 std::cerr << "ContactMapper<TriangleMeshModel>: ERROR invalid contact element index "<<index<<" on a topology with "<<nbt<<" triangles and "<<nbq<<" quads."<<std::endl;
00184 std::cerr << "model="<<this->model->getName()<<" size="<<this->model->getSize()<<std::endl;
00185 return -1;
00186 }
00187 }
00188 }
00189 };
00190
00192 template<class DataTypes>
00193 class ContactMapper<TetrahedronModel, DataTypes> : public BarycentricContactMapper<TetrahedronModel, DataTypes>
00194 {
00195 public:
00196 typedef typename DataTypes::Real Real;
00197 typedef typename DataTypes::Coord Coord;
00198 int addPoint(const Coord& P, int index, Real&)
00199 {
00200 Tetrahedron t(this->model, index);
00201 Vector3 b = t.getBary(P);
00202 return this->mapper->addPointInTetra(index, b.ptr());
00203 }
00204 };
00205
00207 template<class TCollisionModel, class DataTypes>
00208 class IdentityContactMapper : public BaseContactMapper<DataTypes>
00209 {
00210 public:
00211 typedef typename DataTypes::Real Real;
00212 typedef typename DataTypes::Coord Coord;
00213 typedef TCollisionModel MCollisionModel;
00214 typedef typename MCollisionModel::InDataTypes InDataTypes;
00215 typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00216 typedef core::componentmodel::behavior::MechanicalState<typename IdentityContactMapper::DataTypes> MMechanicalState;
00217 typedef component::MechanicalObject<typename IdentityContactMapper::DataTypes> MMechanicalObject;
00218 typedef mapping::IdentityMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00219 MCollisionModel* model;
00220 MMapping* mapping;
00221
00222 IdentityContactMapper()
00223 : model(NULL), mapping(NULL)
00224 {
00225 }
00226
00227 void setCollisionModel(MCollisionModel* model)
00228 {
00229 this->model = model;
00230 }
00231
00232 void cleanup();
00233
00234 MMechanicalState* createMapping(const char* name="contactPoints");
00235
00236 void resize(int size)
00237 {
00238 }
00239
00240 int addPoint(const Coord&, int index, Real&)
00241 {
00242 return index;
00243 }
00244
00245 void update()
00246 {
00247 if (mapping!=NULL)
00248 {
00249 mapping->updateMapping();
00250 }
00251 }
00252 };
00253
00255 template<class TCollisionModel>
00256 class IdentityContactMapper<TCollisionModel, typename TCollisionModel::InDataTypes> : public BaseContactMapper<typename TCollisionModel::InDataTypes>
00257 {
00258 public:
00259 typedef TCollisionModel MCollisionModel;
00260 typedef typename MCollisionModel::InDataTypes InDataTypes;
00261 typedef typename MCollisionModel::InDataTypes DataTypes;
00262 typedef typename DataTypes::Real Real;
00263 typedef typename DataTypes::Coord Coord;
00264 typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00265 typedef core::componentmodel::behavior::MechanicalState<DataTypes> MMechanicalState;
00266 MCollisionModel* model;
00267
00268 IdentityContactMapper()
00269 : model(NULL)
00270 {
00271 }
00272
00273 void setCollisionModel(MCollisionModel* model)
00274 {
00275 this->model = model;
00276 }
00277
00278 void cleanup()
00279 {
00280 }
00281
00282 MMechanicalState* createMapping(const char* ="contactPoints")
00283 {
00284 if (model==NULL) return NULL;
00285 return model->getMechanicalState();
00286 }
00287
00288 void resize(int )
00289 {
00290 }
00291
00292 int addPoint(const Coord& , int index, Real&)
00293 {
00294 return index;
00295 }
00296
00297 void update()
00298 {
00299 }
00300 };
00301
00303 template<class DataTypes>
00304 class ContactMapper<PointModel, DataTypes> : public IdentityContactMapper<PointModel, DataTypes>
00305 {
00306 public:
00307 };
00308
00310 template<class TInDataTypes, class DataTypes>
00311 class ContactMapper<TSphereModel<TInDataTypes>, DataTypes> : public IdentityContactMapper<TSphereModel<TInDataTypes>, DataTypes>
00312 {
00313 public:
00314 typedef typename DataTypes::Real Real;
00315 typedef typename DataTypes::Coord Coord;
00316 int addPoint(const Coord& , int index, Real& r)
00317 {
00318 TSphere<TInDataTypes> e(this->model, index);
00319 r = e.r();
00320 return index;
00321 }
00322 };
00323
00325 template<class DataTypes>
00326 class ContactMapper<SphereTreeModel, DataTypes> : public IdentityContactMapper<SphereTreeModel, DataTypes>
00327 {
00328 public:
00329 typedef typename DataTypes::Real Real;
00330 typedef typename DataTypes::Coord Coord;
00331 int addPoint(const Coord& , int index, Real& r)
00332 {
00333 SingleSphere e(this->model, index);
00334 r = e.r();
00335 return index;
00336 }
00337 };
00338
00340 template < class TCollisionModel, class DataTypes >
00341 class RigidContactMapper : public BaseContactMapper<DataTypes>
00342 {
00343 public:
00344 typedef typename DataTypes::Real Real;
00345 typedef typename DataTypes::Coord Coord;
00346 typedef TCollisionModel MCollisionModel;
00347 typedef typename MCollisionModel::InDataTypes InDataTypes;
00348 typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00349 typedef core::componentmodel::behavior::MechanicalState<typename RigidContactMapper::DataTypes> MMechanicalState;
00350 typedef component::MechanicalObject<typename RigidContactMapper::DataTypes> MMechanicalObject;
00351 typedef mapping::RigidMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00352 MCollisionModel* model;
00353 simulation::tree::GNode* child;
00354 MMapping* mapping;
00355 MMechanicalState* outmodel;
00356 int nbp;
00357
00358 RigidContactMapper()
00359 : model(NULL), child(NULL), mapping(NULL), outmodel(NULL), nbp(0)
00360 {
00361 }
00362
00363 void setCollisionModel(MCollisionModel* model)
00364 {
00365 this->model = model;
00366 }
00367
00368 void cleanup();
00369
00370 MMechanicalState* createMapping(const char* name="contactPoints");
00371
00372 void resize(int size)
00373 {
00374 if (mapping!=NULL)
00375 mapping->clear(size);
00376 if (outmodel!=NULL)
00377 outmodel->resize(size);
00378 nbp = 0;
00379 }
00380
00381 int addPoint(const Coord& P, int index, Real&)
00382 {
00383 int i = nbp++;
00384 if ((int)outmodel->getX()->size() <= i)
00385 outmodel->resize(i+1);
00386 if (mapping)
00387 {
00388 i = mapping->addPoint(P,index);
00389 }
00390 else
00391 {
00392 (*outmodel->getX())[i] = P;
00393 }
00394 return i;
00395 }
00396
00397 void update()
00398 {
00399 if (mapping!=NULL)
00400 {
00401 mapping->updateMapping();
00402 }
00403 }
00404
00405 };
00406
00408 template <class DataTypes>
00409 class ContactMapper<RigidDistanceGridCollisionModel,DataTypes> : public RigidContactMapper<RigidDistanceGridCollisionModel,DataTypes>
00410 {
00411 public:
00412 typedef typename DataTypes::Real Real;
00413 typedef typename DataTypes::Coord Coord;
00414 typedef RigidContactMapper<RigidDistanceGridCollisionModel,DataTypes> Inherit;
00415 typedef typename Inherit::MMechanicalState MMechanicalState;
00416 typedef typename Inherit::MCollisionModel MCollisionModel;
00417 MMechanicalState* createMapping(const char* name="contactPoints");
00418
00419 int addPoint(const Coord& P, int index, Real& r)
00420 {
00421 int i = Inherit::addPoint(P, index, r);
00422 if (!this->mapping)
00423 {
00424 MCollisionModel* model = this->model;
00425 MMechanicalState* outmodel = this->outmodel;
00426 typename DataTypes::Coord& x = (*outmodel->getX())[i];
00427 typename DataTypes::Deriv& v = (*outmodel->getV())[i];
00428 if (model->isTransformed(index))
00429 x = model->getTranslation(index) + model->getRotation(index) * P;
00430 else
00431 x = P;
00432 v = typename DataTypes::Deriv();
00433
00434
00435 double gdt = model->getPrevDt(index);
00436 if (gdt > 0.000001)
00437 {
00438 if (model->isTransformed(index))
00439 {
00440 v = (x - (model->getPrevTranslation(index) + model-> getPrevRotation(index) * P)) * (1.0/gdt);
00441 }
00442 DistanceGrid* prevGrid = model->getPrevGrid(index);
00443
00444
00445 {
00446 DistanceGrid::Coord coefs;
00447 int i = prevGrid->index(P, coefs);
00448 SReal d = prevGrid->interp(i,coefs);
00449 if (rabs(d) < 0.3)
00450 {
00451 DistanceGrid::Coord n = prevGrid->grad(i,coefs);
00452 v += n * (d / ( n.norm() * gdt));
00453
00454 }
00455 }
00456 }
00457 }
00458 return i;
00459 }
00460 };
00461
00463 template <class DataTypes>
00464 class ContactMapper<FFDDistanceGridCollisionModel,DataTypes> : public BarycentricContactMapper<FFDDistanceGridCollisionModel,DataTypes>
00465 {
00466 public:
00467 typedef typename DataTypes::Real Real;
00468 typedef typename DataTypes::Coord Coord;
00469 int addPoint(const Coord& P, int index, Real&)
00470 {
00471 Vector3 bary;
00472 int elem = this->model->getDeformCube(index).elem;
00473 bary = this->model->getDeformCube(index).baryCoords(P);
00474
00475
00476
00477
00478
00479 return this->mapper->addPointInCube(elem,bary.ptr());
00480 }
00481 };
00482
00484 template < class TCollisionModel, class DataTypes >
00485 class SubsetContactMapper : public BaseContactMapper<DataTypes>
00486 {
00487 public:
00488 typedef typename DataTypes::Real Real;
00489 typedef typename DataTypes::Coord Coord;
00490 typedef TCollisionModel MCollisionModel;
00491 typedef typename MCollisionModel::InDataTypes InDataTypes;
00492 typedef core::componentmodel::behavior::MechanicalState<InDataTypes> InMechanicalState;
00493 typedef core::componentmodel::behavior::MechanicalState<typename SubsetContactMapper::DataTypes> MMechanicalState;
00494 typedef component::MechanicalObject<typename SubsetContactMapper::DataTypes> MMechanicalObject;
00495 typedef mapping::SubsetMapping< core::componentmodel::behavior::MechanicalMapping< InMechanicalState, MMechanicalState > > MMapping;
00496 MCollisionModel* model;
00497 simulation::tree::GNode* child;
00498 MMapping* mapping;
00499 MMechanicalState* outmodel;
00500 int nbp;
00501 bool needInit;
00502
00503 SubsetContactMapper()
00504 : model(NULL), child(NULL), mapping(NULL), outmodel(NULL), nbp(0), needInit(false)
00505 {
00506 }
00507
00508 void setCollisionModel(MCollisionModel* model)
00509 {
00510 this->model = model;
00511 }
00512
00513 void cleanup();
00514
00515 MMechanicalState* createMapping(const char* name="contactPoints");
00516
00517 void resize(int size)
00518 {
00519 if (mapping!=NULL)
00520 mapping->clear(size);
00521 if (outmodel!=NULL)
00522 outmodel->resize(size);
00523 nbp = 0;
00524 }
00525
00526 int addPoint(const Coord& P, int index, Real&)
00527 {
00528 int i = nbp++;
00529 if ((int)outmodel->getX()->size() <= i)
00530 outmodel->resize(i+1);
00531 if (mapping)
00532 {
00533 i = mapping->addPoint(index);
00534 needInit = true;
00535 }
00536 else
00537 {
00538 (*outmodel->getX())[i] = P;
00539 }
00540 return i;
00541 }
00542
00543 void update()
00544 {
00545 if (mapping!=NULL)
00546 {
00547 if (needInit)
00548 {
00549 mapping->init();
00550 needInit = false;
00551 }
00552 mapping->updateMapping();
00553 }
00554 }
00555
00556
00557
00558
00559
00560 };
00561
00562 template < class Mapper >
00563 class ContactMapperCreator : public helper::Creator < typename Mapper::ContactMapperFactory, Mapper >
00564 {
00565 public:
00566 typedef helper::Creator < typename Mapper::ContactMapperFactory, Mapper > Inherit;
00567 ContactMapperCreator(std::string name, bool multi = true)
00568 : Inherit(name, multi)
00569 {
00570 }
00571 };
00572
00573 }
00574
00575 }
00576
00577 }
00578
00579 #endif