DistanceGridCollisionModel.h

Go to the documentation of this file.
00001 /******************************************************************************
00002 *       SOFA, Simulation Open-Framework Architecture, version 1.0 beta 3      *
00003 *                (c) 2006-2008 MGH, INRIA, USTL, UJF, CNRS                    *
00004 *                                                                             *
00005 * This library is free software; you can redistribute it and/or modify it     *
00006 * under the terms of the GNU Lesser General Public License as published by    *
00007 * the Free Software Foundation; either version 2.1 of the License, or (at     *
00008 * your option) any later version.                                             *
00009 *                                                                             *
00010 * This library is distributed in the hope that it will be useful, but WITHOUT *
00011 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
00012 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
00013 * for more details.                                                           *
00014 *                                                                             *
00015 * You should have received a copy of the GNU Lesser General Public License    *
00016 * along with this library; if not, write to the Free Software Foundation,     *
00017 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
00018 *******************************************************************************
00019 *                               SOFA :: Modules                               *
00020 *                                                                             *
00021 * Authors: The SOFA Team and external contributors (see Authors.txt)          *
00022 *                                                                             *
00023 * Contact information: contact@sofa-framework.org                             *
00024 ******************************************************************************/
00025 #ifndef SOFA_COMPONENT_COLLISION_DISTANCEGRIDCOLLISIONMODEL_H
00026 #define SOFA_COMPONENT_COLLISION_DISTANCEGRIDCOLLISIONMODEL_H
00027 
00028 #include <sofa/core/CollisionModel.h>
00029 #include <sofa/component/MechanicalObject.h>
00030 #include <sofa/defaulttype/Vec3Types.h>
00031 #include <sofa/defaulttype/RigidTypes.h>
00032 #include <sofa/helper/io/Mesh.h>
00033 #include <sofa/component/topology/RegularGridTopology.h>
00034 
00035 
00036 namespace sofa
00037 {
00038 
00039 namespace component
00040 {
00041 
00042 namespace collision
00043 {
00044 
00045 using namespace sofa::defaulttype;
00046 using namespace sofa::helper;
00047 
00048 class DistanceGrid
00049 {
00050 public:
00051     static SReal maxDist() { return (SReal)1e10; }
00052     typedef Vector3 Coord;
00053     typedef defaulttype::ExtVector<SReal> VecSReal;
00054     typedef defaulttype::ExtVector<Coord> VecCoord;
00055 
00056     DistanceGrid(int nx, int ny, int nz, Coord pmin, Coord pmax);
00057 
00058     DistanceGrid(int nx, int ny, int nz, Coord pmin, Coord pmax, defaulttype::ExtVectorAllocator<SReal>* alloc);
00059 
00060 protected:
00061     ~DistanceGrid();
00062 
00063 public:
00065     static DistanceGrid* load(const std::string& filename, double scale=1.0, int nx=64, int ny=64, int nz=64, Coord pmin = Coord(), Coord pmax = Coord());
00066 
00068     static DistanceGrid* loadShared(const std::string& filename, double scale=1.0, int nx=64, int ny=64, int nz=64, Coord pmin = Coord(), Coord pmax = Coord());
00069 
00071     DistanceGrid* addRef();
00072 
00074     bool release();
00075 
00077     bool save(const std::string& filename);
00078 
00080     void calcDistance(sofa::helper::io::Mesh* mesh, double scale=1.0);
00081 
00084     void calcCubeDistance(SReal dim=1, int np=5);
00085 
00087     void computeBBox();
00088 
00089     int getNx() const { return nx; }
00090     int getNy() const { return ny; }
00091     int getNz() const { return nz; }
00092     const Coord& getCellWidth() const { return cellWidth; }
00093 
00094     int size() const { return nxnynz; }
00095 
00096     const Coord& getBBMin() const { return bbmin; }
00097     const Coord& getBBMax() const { return bbmax; }
00098     void setBBMin(const Coord& val) { bbmin = val; }
00099     void setBBMax(const Coord& val) { bbmax = val; }
00100     Coord getBBCorner(int i) const { return Coord((i&1)?bbmax[0]:bbmin[0],(i&2)?bbmax[1]:bbmin[1],(i&4)?bbmax[2]:bbmin[2]); }
00101     bool inBBox(const Coord& p, SReal margin=0.0f) const
00102     {
00103     for (int c=0;c<3;++c)
00104         if (p[c] < bbmin[c]-margin || p[c] > bbmax[c]+margin) return false;
00105     return true;
00106     }
00107 
00108     const Coord& getPMin() const { return pmin; }
00109     const Coord& getPMax() const { return pmax; }
00110     Coord getCorner(int i) const { return Coord((i&1)?pmax[0]:pmin[0],(i&2)?pmax[1]:pmin[1],(i&4)?pmax[2]:pmin[2]); }
00111 
00112     bool isCube() const { return cubeDim != 0; }
00113     SReal getCubeDim() const { return cubeDim; }
00114 
00115     bool inGrid(const Coord& p) const
00116     {
00117         Coord epsilon = cellWidth*0.1;
00118     for (int c=0;c<3;++c)
00119         if (p[c] < pmin[c]+epsilon[c] || p[c] > pmax[c]-epsilon[c]) return false;
00120     return true;
00121     }
00122 
00123     Coord clamp(Coord p) const
00124     {
00125     for (int c=0;c<3;++c)
00126         if (p[c] < pmin[c]) p[c] = pmin[c];
00127         else if (p[c] > pmax[c]) p[c] = pmax[c];
00128     return p;
00129     }
00130 
00131     int ix(const Coord& p) const
00132     {
00133     return rfloor((p[0]-pmin[0])*invCellWidth[0]);
00134     }
00135 
00136     int iy(const Coord& p) const
00137     {
00138     return rfloor((p[1]-pmin[1])*invCellWidth[1]);
00139     }
00140 
00141     int iz(const Coord& p) const
00142     {
00143     return rfloor((p[2]-pmin[2])*invCellWidth[2]);
00144     }
00145 
00146     int index(const Coord& p, Coord& coefs) const
00147     {
00148     coefs[0] = (p[0]-pmin[0])*invCellWidth[0];
00149     coefs[1] = (p[1]-pmin[1])*invCellWidth[1];
00150     coefs[2] = (p[2]-pmin[2])*invCellWidth[2];
00151     int x = rfloor(coefs[0]);
00152     if (x<0) x=0; else if (x>=nx-1) x=nx-2;
00153     coefs[0] -= x;
00154     int y = rfloor(coefs[1]);
00155     if (y<0) y=0; else if (y>=ny-1) y=ny-2;
00156     coefs[1] -= y;
00157     int z = rfloor(coefs[2]);
00158     if (z<0) z=0; else if (z>=nz-1) z=nz-2;
00159     coefs[2] -= z;
00160     return x+nx*(y+ny*(z));
00161     }
00162 
00163     int index(const Coord& p) const
00164     {
00165     Coord coefs;
00166     return index(p, coefs);
00167     }
00168 
00169     int index(int x, int y, int z)
00170     {
00171     return x+nx*(y+ny*(z));
00172     }
00173 
00174     Coord coord(int x, int y, int z)
00175     {
00176     return pmin+Coord(x*cellWidth[0], y*cellWidth[1], z*cellWidth[2]);
00177     }
00178 
00179     SReal operator[](int index) const { return dists[index]; }
00180     SReal& operator[](int index) { return dists[index]; }
00181 
00182     static SReal interp(SReal coef, SReal a, SReal b)
00183     {
00184     return a+coef*(b-a);
00185     }
00186 
00187     SReal interp(int index, const Coord& coefs) const
00188     {
00189         return interp(coefs[2],interp(coefs[1],interp(coefs[0],dists[index          ],dists[index+1        ]),
00190                                                interp(coefs[0],dists[index  +nx     ],dists[index+1+nx     ])),
00191                                interp(coefs[1],interp(coefs[0],dists[index     +nxny],dists[index+1   +nxny]),
00192                                                interp(coefs[0],dists[index  +nx+nxny],dists[index+1+nx+nxny])));
00193     }
00194 
00195     SReal interp(const Coord& p) const
00196     {
00197     Coord coefs;
00198     int i = index(p, coefs);
00199     return interp(i, coefs);
00200     }
00201     
00202     Coord grad(int index, const Coord& coefs) const
00203     {
00204         // val = dist[0][0][0] * (1-x) * (1-y) * (1-z)
00205         //     + dist[1][0][0] * (  x) * (1-y) * (1-z)
00206         //     + dist[0][1][0] * (1-x) * (  y) * (1-z)
00207         //     + dist[1][1][0] * (  x) * (  y) * (1-z)
00208         //     + dist[0][0][1] * (1-x) * (1-y) * (  z)
00209         //     + dist[1][0][1] * (  x) * (1-y) * (  z)
00210         //     + dist[0][1][1] * (1-x) * (  y) * (  z)
00211         //     + dist[1][1][1] * (  x) * (  y) * (  z)
00212         // dval / dx = (dist[1][0][0]-dist[0][0][0]) * (1-y) * (1-z)
00213         //           + (dist[1][1][0]-dist[0][1][0]) * (  y) * (1-z)
00214         //           + (dist[1][0][1]-dist[0][0][1]) * (1-y) * (  z)
00215         //           + (dist[1][1][1]-dist[0][1][1]) * (  y) * (  z)
00216         const SReal dist000 = dists[index          ];
00217         const SReal dist100 = dists[index+1        ];
00218         const SReal dist010 = dists[index  +nx     ];
00219         const SReal dist110 = dists[index+1+nx     ];
00220         const SReal dist001 = dists[index     +nxny];
00221         const SReal dist101 = dists[index+1   +nxny];
00222         const SReal dist011 = dists[index  +nx+nxny];
00223         const SReal dist111 = dists[index+1+nx+nxny];
00224         return Coord(
00225             interp(coefs[2],interp(coefs[1],dist100-dist000,dist110-dist010),interp(coefs[1],dist101-dist001,dist111-dist011)), //*invCellWidth[0],
00226             interp(coefs[2],interp(coefs[0],dist010-dist000,dist110-dist100),interp(coefs[0],dist011-dist001,dist111-dist101)), //*invCellWidth[1],
00227             interp(coefs[1],interp(coefs[0],dist001-dist000,dist101-dist100),interp(coefs[0],dist011-dist010,dist111-dist110))); //*invCellWidth[2]);
00228     }
00229 
00230     Coord grad(const Coord& p) const
00231     {
00232     Coord coefs;
00233     int i = index(p, coefs);
00234     return grad(i, coefs);
00235     }
00236 
00237     SReal eval(const Coord& x) const
00238     {
00239     SReal d;
00240     if (inGrid(x))
00241     {
00242         d = interp(x);
00243     }
00244     else
00245     {
00246         Coord xclamp = clamp(x);
00247         d = interp(xclamp);
00248         d = rsqrt((x-xclamp).norm2() + d*d); // we underestimate the distance
00249     }
00250     return d;
00251     }
00252 
00253     SReal quickeval(const Coord& x) const
00254     {
00255     SReal d;
00256     if (inGrid(x))
00257     {
00258         d = dists[index(x)] - cellWidth[0]; // we underestimate the distance
00259     }
00260     else
00261     {
00262         Coord xclamp = clamp(x);
00263         d = dists[index(xclamp)] - cellWidth[0]; // we underestimate the distance
00264         d = rsqrt((x-xclamp).norm2() + d*d);
00265     }
00266     return d;
00267     }
00268 
00269     SReal eval2(const Coord& x) const
00270     {
00271     SReal d2;
00272     if (inGrid(x))
00273     {
00274         SReal d = interp(x);
00275         d2 = d*d;
00276     }
00277     else
00278     {
00279         Coord xclamp = clamp(x);
00280         SReal d = interp(xclamp);
00281         d2 = ((x-xclamp).norm2() + d*d); // we underestimate the distance
00282     }
00283     return d2;
00284     }
00285 
00286     SReal quickeval2(const Coord& x) const
00287     {
00288     SReal d2;
00289     if (inGrid(x))
00290     {
00291         SReal d = dists[index(x)] - cellWidth[0]; // we underestimate the distance
00292         d2 = d*d;
00293     }
00294     else
00295     {
00296         Coord xclamp = clamp(x);
00297         SReal d = dists[index(xclamp)] - cellWidth[0]; // we underestimate the distance
00298         d2 = ((x-xclamp).norm2() + d*d);
00299     }
00300     return d2;
00301     }
00302 
00303     VecCoord meshPts;
00304 
00305 protected:
00306     int nbRef;
00307     VecSReal dists;
00308     const int nx,ny,nz, nxny, nxnynz;
00309     const Coord pmin, pmax;
00310     const Coord cellWidth, invCellWidth;
00311     Coord bbmin, bbmax; 
00312 
00313     SReal cubeDim; 
00314 
00315     // Fast Marching Method Update
00316     enum Status { FMM_FRONT0 = 0, FMM_FAR = -1, FMM_KNOWN_OUT = -2, FMM_KNOWN_IN = -3 };
00317     helper::vector<int> fmm_status;
00318     helper::vector<int> fmm_heap;
00319     int fmm_heap_size;
00320 
00321     int fmm_pop();
00322     void fmm_push(int index);
00323     void fmm_swap(int entry1, int entry2);
00324 
00325     // Grid shared resources
00326 
00327     struct DistanceGridParams
00328     {
00329         std::string filename;
00330         double scale;
00331     int nx,ny,nz;
00332     Coord pmin,pmax;
00333     bool operator==(const DistanceGridParams& v) const
00334     {
00335         if (!(filename == v.filename)) return false;
00336         if (!(scale    == v.scale   )) return false;
00337         if (!(nx       == v.nx      )) return false;
00338         if (!(ny       == v.ny      )) return false;
00339         if (!(nz       == v.nz      )) return false;
00340         if (!(pmin[0]  == v.pmin[0] )) return false;
00341         if (!(pmin[1]  == v.pmin[1] )) return false;
00342         if (!(pmin[2]  == v.pmin[2] )) return false;
00343         if (!(pmax[0]  == v.pmax[0] )) return false;
00344         if (!(pmax[1]  == v.pmax[1] )) return false;
00345         if (!(pmax[2]  == v.pmax[2] )) return false;
00346         return true;
00347     }
00348     bool operator<(const DistanceGridParams& v) const
00349     {
00350         if (filename < v.filename) return true;
00351         if (filename > v.filename) return false;
00352         if (scale    < v.scale   ) return true;
00353         if (scale    > v.scale   ) return false;
00354         if (nx       < v.nx      ) return false;
00355         if (nx       > v.nx      ) return true;
00356         if (ny       < v.ny      ) return false;
00357         if (ny       > v.ny      ) return true;
00358         if (nz       < v.nz      ) return false;
00359         if (nz       > v.nz      ) return true;
00360         if (pmin[0]  < v.pmin[0] ) return false;
00361         if (pmin[0]  > v.pmin[0] ) return true;
00362         if (pmin[1]  < v.pmin[1] ) return false;
00363         if (pmin[1]  > v.pmin[1] ) return true;
00364         if (pmin[2]  < v.pmin[2] ) return false;
00365         if (pmin[2]  > v.pmin[2] ) return true;
00366         if (pmax[0]  < v.pmax[0] ) return false;
00367         if (pmax[0]  > v.pmax[0] ) return true;
00368         if (pmax[1]  < v.pmax[1] ) return false;
00369         if (pmax[1]  > v.pmax[1] ) return true;
00370         if (pmax[2]  < v.pmax[2] ) return false;
00371         if (pmax[2]  > v.pmax[2] ) return true;
00372         return false;
00373     }
00374     bool operator>(const DistanceGridParams& v) const
00375     {
00376         if (filename > v.filename) return true;
00377         if (filename < v.filename) return false;
00378         if (scale    > v.scale   ) return true;
00379         if (scale    < v.scale   ) return false;
00380         if (nx       > v.nx      ) return false;
00381         if (nx       < v.nx      ) return true;
00382         if (ny       > v.ny      ) return false;
00383         if (ny       < v.ny      ) return true;
00384         if (nz       > v.nz      ) return false;
00385         if (nz       < v.nz      ) return true;
00386         if (pmin[0]  > v.pmin[0] ) return false;
00387         if (pmin[0]  < v.pmin[0] ) return true;
00388         if (pmin[1]  > v.pmin[1] ) return false;
00389         if (pmin[1]  < v.pmin[1] ) return true;
00390         if (pmin[2]  > v.pmin[2] ) return false;
00391         if (pmin[2]  < v.pmin[2] ) return true;
00392         if (pmax[0]  > v.pmax[0] ) return false;
00393         if (pmax[0]  < v.pmax[0] ) return true;
00394         if (pmax[1]  > v.pmax[1] ) return false;
00395         if (pmax[1]  < v.pmax[1] ) return true;
00396         if (pmax[2]  > v.pmax[2] ) return false;
00397         if (pmax[2]  < v.pmax[2] ) return true;
00398         return false;
00399     }
00400     };
00401     static std::map<DistanceGridParams, DistanceGrid*>& getShared();
00402 
00403 };
00404 
00408 
00409 class RigidDistanceGridCollisionModel;
00410 
00411 class RigidDistanceGridCollisionElement : public core::TCollisionElementIterator<RigidDistanceGridCollisionModel>
00412 {
00413 public:
00414   
00415     RigidDistanceGridCollisionElement(RigidDistanceGridCollisionModel* model, int index);
00416 
00417     explicit RigidDistanceGridCollisionElement(core::CollisionElementIterator& i);
00418 
00419     DistanceGrid* getGrid();
00420 
00421     bool isTransformed();
00422     const Matrix3& getRotation();
00423     const Vector3& getTranslation();
00424 
00425     void setGrid(DistanceGrid* surf);
00426 
00430     DistanceGrid* getPrevGrid();
00431     const Matrix3& getPrevRotation();
00432     const Vector3& getPrevTranslation();
00433     double getPrevDt();
00435     
00437     void setNewState(double dt, DistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00438 };
00439 
00440 class RigidDistanceGridCollisionModel : public core::CollisionModel
00441 {
00442 protected:
00443 
00444     class ElementData
00445     {
00446     public:
00447         Matrix3 rotation;
00448         Vector3 translation;
00449         DistanceGrid* grid;
00450         
00454         DistanceGrid* prevGrid; 
00455         Matrix3 prevRotation; 
00456         Vector3 prevTranslation; 
00457         double prevDt; 
00458 
00459         
00460         bool isTransformed; 
00461         ElementData() : grid(NULL), prevGrid(NULL), prevDt(0.0), isTransformed(false) { rotation.identity(); prevRotation.identity(); }
00462     };
00463 
00464     sofa::helper::vector<ElementData> elems;
00465     bool modified;
00466 
00467     // Input data parameters
00468     Data< std::string > filename;
00469     Data< double > scale;
00470     Data< helper::fixed_array<DistanceGrid::Coord,2> > box;
00471     Data< int > nx;
00472     Data< int > ny;
00473     Data< int > nz;
00474     Data< std::string > dumpfilename;
00475 
00476     core::componentmodel::behavior::MechanicalState<RigidTypes>* rigid;
00477 
00478     void updateGrid();
00479 public:
00480     typedef Rigid3Types InDataTypes;
00481     typedef Vec3Types DataTypes;
00482     typedef RigidDistanceGridCollisionElement Element;
00483 
00484     Data< bool > usePoints;
00485 
00486     RigidDistanceGridCollisionModel();
00487 
00488     ~RigidDistanceGridCollisionModel();
00489 
00490     core::componentmodel::behavior::MechanicalState<InDataTypes>* getRigidModel() { return rigid; }
00491     core::componentmodel::behavior::MechanicalState<InDataTypes>* getMechanicalState() { return rigid; }
00492 
00493     void init();
00494 
00495     DistanceGrid* getGrid(int index=0)
00496     {
00497         return elems[index].grid;
00498     }
00499     bool isTransformed(int index=0)
00500     {
00501         return elems[index].isTransformed;
00502     }
00503     const Matrix3& getRotation(int index=0)
00504     {
00505         return elems[index].rotation;
00506     }
00507     const Vector3& getTranslation(int index=0)
00508     {
00509         return elems[index].translation;
00510     }
00511 
00512     void setGrid(DistanceGrid* surf, int index=0);
00513 
00514     DistanceGrid* getPrevGrid(int index=0)
00515     {
00516         return elems[index].prevGrid;
00517     }
00518     const Matrix3& getPrevRotation(int index=0)
00519     {
00520         return elems[index].prevRotation;
00521     }
00522     const Vector3& getPrevTranslation(int index=0)
00523     {
00524         return elems[index].prevTranslation;
00525     }
00526     double getPrevDt(int index=0)
00527     {
00528         return elems[index].prevDt;
00529     }
00530     
00532     void setNewState(int index, double dt, DistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00533     
00535     
00537     void setNewState(double dt, DistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00538 
00539     // -- CollisionModel interface
00540 
00541     void resize(int size);
00542 
00544     void computeBoundingTree(int maxDepth=0);
00545 
00546     void draw(int index);
00547 
00548     void draw();
00549 };
00550 
00551 inline RigidDistanceGridCollisionElement::RigidDistanceGridCollisionElement(RigidDistanceGridCollisionModel* model, int index)
00552 : core::TCollisionElementIterator<RigidDistanceGridCollisionModel>(model, index)
00553 {}
00554 
00555 inline RigidDistanceGridCollisionElement::RigidDistanceGridCollisionElement(core::CollisionElementIterator& i)
00556 : core::TCollisionElementIterator<RigidDistanceGridCollisionModel>(static_cast<RigidDistanceGridCollisionModel*>(i.getCollisionModel()), i.getIndex())
00557 {
00558 }
00559 
00560 inline DistanceGrid* RigidDistanceGridCollisionElement::getGrid() { return model->getGrid(index); }
00561 inline void RigidDistanceGridCollisionElement::setGrid(DistanceGrid* surf) { return model->setGrid(surf, index); }
00562 
00563 inline bool RigidDistanceGridCollisionElement::isTransformed() { return model->isTransformed(index); }
00564 inline const Matrix3& RigidDistanceGridCollisionElement::getRotation() { return model->getRotation(index); }
00565 inline const Vector3& RigidDistanceGridCollisionElement::getTranslation() { return model->getTranslation(index); }
00566 
00567 inline DistanceGrid* RigidDistanceGridCollisionElement::getPrevGrid() { return model->getPrevGrid(index); }
00568 inline const Matrix3& RigidDistanceGridCollisionElement::getPrevRotation() { return model->getPrevRotation(index); }
00569 inline const Vector3& RigidDistanceGridCollisionElement::getPrevTranslation() { return model->getPrevTranslation(index); }
00570 inline double RigidDistanceGridCollisionElement::getPrevDt() { return model->getPrevDt(index); }
00571 
00572 inline void RigidDistanceGridCollisionElement::setNewState(double dt, DistanceGrid* grid, const Matrix3& rotation, const Vector3& translation)
00573 {
00574     return model->setNewState(dt, grid, rotation, translation);
00575 }
00576 
00580 
00581 class FFDDistanceGridCollisionModel;
00582 
00583 class FFDDistanceGridCollisionElement : public core::TCollisionElementIterator<FFDDistanceGridCollisionModel>
00584 {
00585 public:
00586   
00587     FFDDistanceGridCollisionElement(FFDDistanceGridCollisionModel* model, int index);
00588 
00589     explicit FFDDistanceGridCollisionElement(core::CollisionElementIterator& i);
00590 
00591     DistanceGrid* getGrid();
00592 
00593     void setGrid(DistanceGrid* surf);
00594 };
00595 
00596 class FFDDistanceGridCollisionModel : public core::CollisionModel
00597 {
00598 public:
00599     typedef SReal GSReal;
00600     typedef DistanceGrid::Coord GCoord;
00601     class DeformedCube
00602     {
00603     public:
00604         DistanceGrid* grid;
00605         DeformedCube() : grid(NULL) {}
00606         int elem; 
00607         struct Point
00608         {
00609             GCoord bary; 
00610             int index; 
00611         };
00612         vector<Point> points; 
00613         GCoord initP0,initDP,invDP; 
00614         GCoord corners[8]; 
00615         enum {C000 = 0+0+0,
00616               C100 = 1+0+0,
00617               C010 = 0+2+0,
00618               C110 = 1+2+0,
00619               C001 = 0+0+4,
00620               C101 = 1+0+4,
00621               C011 = 0+2+4,
00622               C111 = 1+2+4};
00623         typedef Vec<4,GSReal> Plane; 
00624         Plane faces[6]; 
00625         enum {FX0 = 0+0,
00626               FX1 = 0+1,
00627               FY0 = 2+0,
00628               FY1 = 2+1,
00629               FZ0 = 4+0,
00630               FZ1 = 4+1};
00637         GCoord Dx;   
00638         GCoord Dy;   
00639         GCoord Dz;   
00640         GCoord Dxy;  
00641         GCoord Dxz;  
00642         GCoord Dyz;  
00643         GCoord Dxyz; 
00644 
00645 
00646         void updateDeform();
00647         
00648         GCoord center; 
00649         GSReal radius; 
00650         vector<GCoord> deformedPoints; 
00651         bool pointsUpdated; 
00652         void updatePoints(); 
00653         bool facesUpdated; 
00654         void updateFaces(); 
00655 
00656         DistanceGrid::Coord baryCoords(const GCoord& c) const
00657         {
00658             return GCoord( (c[0]-initP0[0])*invDP[0],
00659                            (c[1]-initP0[1])*invDP[1],
00660                            (c[2]-initP0[2])*invDP[2]);
00661         }
00663         GCoord initpos(const GCoord& b) const
00664         {
00665             return GCoord( initP0[0]+initDP[0]*b[0],
00666                            initP0[1]+initDP[1]*b[1],
00667                            initP0[2]+initDP[2]*b[2]);
00668         }
00670         GCoord deform(const GCoord& b) const
00671         {
00672             return corners[C000] + Dx*b[0] + (Dy + Dxy*b[0])*b[1] + (Dz + Dxz*b[0] + (Dyz + Dxyz*b[0])*b[1])*b[2];
00673         }
00674 
00675         static GSReal interp(GSReal coef, GSReal a, GSReal b)
00676         {
00677             return a+coef*(b-a);
00678         }
00679 
00681         GCoord deformDir(const GCoord& b, const GCoord& dir) const
00682         {
00683             GCoord r;
00684             // dp/dx = Dx + Dxy*y + Dxz*z + Dxyz*y*z
00685             r  = (Dx + Dxy*b[1] + (Dxz + Dxyz*b[1])*b[2])*dir[0];
00686             // dp/dy = Dy + Dxy*x + Dyz*z + Dxyz*x*z
00687             r += (Dy + Dxy*b[0] + (Dyz + Dxyz*b[0])*b[2])*dir[1];
00688             // dp/dz = Dz + Dxz*x + Dyz*y + Dxyz*x*y
00689             r += (Dz + Dxz*b[0] + (Dyz + Dxyz*b[0])*b[1])*dir[2];
00690             return r;
00691         }
00692 
00694         Mat<3,3,double> Jdeform(const GCoord& b) const
00695         {
00696             Mat<3,3,double> J;
00697             for (int i=0;i<3;i++)
00698             {
00699                 // dp/dx = Dx + Dxy*y + Dxz*z + Dxyz*y*z
00700                 J[i][0] = (Dx[i] + Dxy[i]*b[1] + (Dxz[i] + Dxyz[i]*b[1])*b[2]);
00701                 // dp/dy = Dy + Dxy*x + Dyz*z + Dxyz*x*z
00702                 J[i][1] = (Dy[i] + Dxy[i]*b[0] + (Dyz[i] + Dxyz[i]*b[0])*b[2]);
00703                 // dp/dz = Dz + Dxz*x + Dyz*y + Dxyz*x*y
00704                 J[i][2] = (Dz[i] + Dxz[i]*b[0] + (Dyz[i] + Dxyz[i]*b[0])*b[1]);
00705             }
00706             return J;
00707         }
00708 
00710         GCoord undeform0(const GCoord& p) const
00711         {
00712             GCoord b;
00713             for (int i=0;i<3;i++)
00714             {
00715                 GSReal b0 = faces[2*i+0]*Plane(p,1);
00716                 GSReal b1 = faces[2*i+1]*Plane(p,1);
00717                 b[i] = b0 / (b0 + b1);
00718             }
00719             return b;
00720         }
00722         GCoord undeformDir(const GCoord& b, const GCoord& dir) const
00723         {
00724             // we want to find b2 so that deform(b2)-deform(b) = dir
00725             // we can use Newton's method using the jacobian of the deformation.
00726             Mat<3,3,double> m = Jdeform(b);
00727             Mat<3,3,double> minv;
00728             minv.invert(m);
00729             return minv*dir;
00730         }
00731         
00733         Plane computePlane(int c00, int c10, int c01, int c11);
00734     };
00735 
00736 protected:
00737 
00738     sofa::helper::vector<DeformedCube> elems;
00739 
00740     // Input data parameters
00741     Data< std::string > filename;
00742     Data< double > scale;
00743     Data< helper::fixed_array<DistanceGrid::Coord,2> > box;
00744     Data< int > nx;
00745     Data< int > ny;
00746     Data< int > nz;
00747     Data< std::string > dumpfilename;
00748 
00749     core::componentmodel::behavior::MechanicalState<Vec3Types>* ffd;
00750     topology::RegularGridTopology* ffdGrid;
00751 
00752     void updateGrid();
00753 public:
00754     typedef Vec3Types InDataTypes;
00755     typedef Vec3Types DataTypes;
00756     typedef topology::RegularGridTopology Topology;
00757     typedef FFDDistanceGridCollisionElement Element;
00758 
00759     Data< bool > usePoints;
00760 
00761     FFDDistanceGridCollisionModel();
00762 
00763     ~FFDDistanceGridCollisionModel();
00764 
00765     core::componentmodel::behavior::MechanicalState<DataTypes>* getDeformModel() { return ffd; }
00766     topology::RegularGridTopology* getDeformGrid() { return ffdGrid; }
00767 
00768     // alias used by ContactMapper
00769 
00770     core::componentmodel::behavior::MechanicalState<DataTypes>* getMechanicalState() { return ffd; }
00771     topology::RegularGridTopology* getMeshTopology() { return ffdGrid; }
00772 
00773     void init();
00774 
00775     DistanceGrid* getGrid(int index=0)
00776     {
00777         return elems[index].grid;
00778     }
00779 
00780     DeformedCube& getDeformCube(int index=0)
00781     {
00782         return elems[index];
00783     }
00784 
00785     void setGrid(DistanceGrid* surf, int index=0);
00786 
00787     // -- CollisionModel interface
00788 
00789     void resize(int size);
00790 
00792     void computeBoundingTree(int maxDepth=0);
00793 
00794     void draw(int index);
00795 
00796     void draw();
00797 };
00798 
00799 inline FFDDistanceGridCollisionElement::FFDDistanceGridCollisionElement(FFDDistanceGridCollisionModel* model, int index)
00800 : core::TCollisionElementIterator<FFDDistanceGridCollisionModel>(model, index)
00801 {}
00802 
00803 inline FFDDistanceGridCollisionElement::FFDDistanceGridCollisionElement(core::CollisionElementIterator& i)
00804 : core::TCollisionElementIterator<FFDDistanceGridCollisionModel>(static_cast<FFDDistanceGridCollisionModel*>(i.getCollisionModel()), i.getIndex())
00805 {
00806 }
00807 
00808 inline DistanceGrid* FFDDistanceGridCollisionElement::getGrid() { return model->getGrid(index); }
00809 inline void FFDDistanceGridCollisionElement::setGrid(DistanceGrid* surf) { return model->setGrid(surf, index); }
00810 
00811 } // namespace collision
00812 
00813 } // namespace component
00814 
00815 } // namespace sofa
00816 
00817 #endif

Generated on Sun Nov 23 02:33:46 2008 for Sofa by  doxygen 1.5.7.1