CudaDistanceGridCollisionModel.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_GPU_CUDA_CUDADISTANCEGRIDCOLLISIONMODEL_H
00026 #define SOFA_GPU_CUDA_CUDADISTANCEGRIDCOLLISIONMODEL_H
00027 
00028 #include "CudaTypes.h"
00029 
00030 #include <sofa/core/CollisionModel.h>
00031 #include <sofa/component/MechanicalObject.h>
00032 #include <sofa/defaulttype/Vec3Types.h>
00033 #include <sofa/defaulttype/RigidTypes.h>
00034 #include <sofa/helper/io/Mesh.h>
00035 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00036 
00037 namespace sofa
00038 {
00039 
00040 namespace gpu
00041 {
00042 
00043 namespace cuda
00044 {
00045 
00046 using namespace sofa::defaulttype;
00047 //using namespace sofa::component::collision;
00048 
00049 class CudaDistanceGrid
00050 {
00051 public:
00052     typedef float Real;
00053     static Real maxDist() { return (Real)1e10; }
00054     typedef Vec3f Coord;
00055     //typedef Vec4f SamplingPoint; ///< 3D coordinates + radius
00056     typedef CudaVector<Real> VecReal;
00057     typedef CudaVector<Coord> VecCoord;
00058 
00059     CudaDistanceGrid(int nx, int ny, int nz, Coord pmin, Coord pmax);
00060 
00061 protected:
00062     ~CudaDistanceGrid();
00063 
00064 public:
00065 
00067     static CudaDistanceGrid* load(const std::string& filename, double scale=1.0, int nx=64, int ny=64, int nz=64, Coord pmin = Coord(), Coord pmax = Coord());
00068 
00070     static CudaDistanceGrid* loadShared(const std::string& filename, double scale=1.0, int nx=64, int ny=64, int nz=64, Coord pmin = Coord(), Coord pmax = Coord());
00071 
00073     CudaDistanceGrid* addRef();
00074 
00076     bool release();
00077 
00079     bool save(const std::string& filename);
00080 
00082     void calcDistance();
00083 
00086     void calcCubeDistance(Real dim=1, int np=5);
00087 
00089     void computeBBox();
00090 
00091     int getNx() const { return nx; }
00092     int getNy() const { return ny; }
00093     int getNz() const { return nz; }
00094     const Coord& getCellWidth() const { return cellWidth; }
00095     const Coord& getInvCellWidth() const { return invCellWidth; }
00096     const VecReal& getDists() const { return dists; }
00097     VecReal& getDists() { return dists; }
00098 
00099     int size() const { return nxnynz; }
00100 
00101     const Coord& getBBMin() const { return bbmin; }
00102     const Coord& getBBMax() const { return bbmax; }
00103     void setBBMin(const Coord& val) { bbmin = val; }
00104     void setBBMax(const Coord& val) { bbmax = val; }
00105     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]); }
00106     bool inBBox(const Coord& p, Real margin=0.0f) const
00107     {
00108     for (int c=0;c<3;++c)
00109         if (p[c] < bbmin[c]-margin || p[c] > bbmax[c]+margin) return false;
00110     return true;
00111     }
00112 
00113     const Coord& getPMin() const { return pmin; }
00114     const Coord& getPMax() const { return pmax; }
00115     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]); }
00116 
00117     bool isCube() const { return cubeDim != 0; }
00118     Real getCubeDim() const { return cubeDim; }
00119 
00120     bool inGrid(const Coord& p) const
00121     {
00122         Coord epsilon = cellWidth*0.1;
00123     for (int c=0;c<3;++c)
00124         if (p[c] < pmin[c]+epsilon[c] || p[c] > pmax[c]-epsilon[c]) return false;
00125     return true;
00126     }
00127 
00128     Coord clamp(Coord p) const
00129     {
00130     for (int c=0;c<3;++c)
00131         if (p[c] < pmin[c]) p[c] = pmin[c];
00132         else if (p[c] > pmax[c]) p[c] = pmax[c];
00133     return p;
00134     }
00135 
00136     int ix(const Coord& p) const
00137     {
00138     return helper::rfloor((p[0]-pmin[0])*invCellWidth[0]);
00139     }
00140 
00141     int iy(const Coord& p) const
00142     {
00143     return helper::rfloor((p[1]-pmin[1])*invCellWidth[1]);
00144     }
00145 
00146     int iz(const Coord& p) const
00147     {
00148     return helper::rfloor((p[2]-pmin[2])*invCellWidth[2]);
00149     }
00150 
00151     int index(const Coord& p, Coord& coefs) const
00152     {
00153     coefs[0] = (p[0]-pmin[0])*invCellWidth[0];
00154     coefs[1] = (p[1]-pmin[1])*invCellWidth[1];
00155     coefs[2] = (p[2]-pmin[2])*invCellWidth[2];
00156     int x = helper::rfloor(coefs[0]);
00157     if (x==-1) x=0; else if (x==nx-1) x=nx-2;
00158     coefs[0] -= x;
00159     int y = helper::rfloor(coefs[1]);
00160     if (y==-1) y=0; else if (y==ny-1) y=ny-2;
00161     coefs[1] -= y;
00162     int z = helper::rfloor(coefs[2]);
00163     if (z==-1) z=0; else if (z==nz-1) z=nz-2;
00164     coefs[2] -= z;
00165     return x+nx*(y+ny*(z));
00166     }
00167 
00168     int index(const Coord& p) const
00169     {
00170     Coord coefs;
00171     return index(p, coefs);
00172     }
00173 
00174     int index(int x, int y, int z)
00175     {
00176     return x+nx*(y+ny*(z));
00177     }
00178 
00179     Coord coord(int x, int y, int z)
00180     {
00181     return pmin+Coord(x*cellWidth[0], y*cellWidth[1], z*cellWidth[2]);
00182     }
00183 
00184     Real operator[](int index) const { return dists[index]; }
00185     Real& operator[](int index) { return dists[index]; }
00186 
00187     static Real interp(Real coef, Real a, Real b)
00188     {
00189     return a+coef*(b-a);
00190     }
00191 
00192     Real interp(int index, const Coord& coefs) const
00193     {
00194         return interp(coefs[2],interp(coefs[1],interp(coefs[0],dists[index          ],dists[index+1        ]),
00195                                                interp(coefs[0],dists[index  +nx     ],dists[index+1+nx     ])),
00196                                interp(coefs[1],interp(coefs[0],dists[index     +nxny],dists[index+1   +nxny]),
00197                                                interp(coefs[0],dists[index  +nx+nxny],dists[index+1+nx+nxny])));
00198     }
00199 
00200     Real interp(const Coord& p) const
00201     {
00202     Coord coefs;
00203     int i = index(p, coefs);
00204     return interp(i, coefs);
00205     }
00206     
00207     Coord grad(int index, const Coord& coefs) const
00208     {
00209         // val = dist[0][0][0] * (1-x) * (1-y) * (1-z)
00210         //     + dist[1][0][0] * (  x) * (1-y) * (1-z)
00211         //     + dist[0][1][0] * (1-x) * (  y) * (1-z)
00212         //     + dist[1][1][0] * (  x) * (  y) * (1-z)
00213         //     + dist[0][0][1] * (1-x) * (1-y) * (  z)
00214         //     + dist[1][0][1] * (  x) * (1-y) * (  z)
00215         //     + dist[0][1][1] * (1-x) * (  y) * (  z)
00216         //     + dist[1][1][1] * (  x) * (  y) * (  z)
00217         // dval / dx = (dist[1][0][0]-dist[0][0][0]) * (1-y) * (1-z)
00218         //           + (dist[1][1][0]-dist[0][1][0]) * (  y) * (1-z)
00219         //           + (dist[1][0][1]-dist[0][0][1]) * (1-y) * (  z)
00220         //           + (dist[1][1][1]-dist[0][1][1]) * (  y) * (  z)
00221         const Real dist000 = dists[index          ];
00222         const Real dist100 = dists[index+1        ];
00223         const Real dist010 = dists[index  +nx     ];
00224         const Real dist110 = dists[index+1+nx     ];
00225         const Real dist001 = dists[index     +nxny];
00226         const Real dist101 = dists[index+1   +nxny];
00227         const Real dist011 = dists[index  +nx+nxny];
00228         const Real dist111 = dists[index+1+nx+nxny];
00229         return Coord(
00230             interp(coefs[2],interp(coefs[1],dist100-dist000,dist110-dist010),interp(coefs[1],dist101-dist001,dist111-dist011)), //*invCellWidth[0],
00231             interp(coefs[2],interp(coefs[0],dist010-dist000,dist110-dist100),interp(coefs[0],dist011-dist001,dist111-dist101)), //*invCellWidth[1],
00232             interp(coefs[1],interp(coefs[0],dist001-dist000,dist101-dist100),interp(coefs[0],dist011-dist010,dist111-dist110))); //*invCellWidth[2]);
00233     }
00234 
00235     Coord grad(const Coord& p) const
00236     {
00237     Coord coefs;
00238     int i = index(p, coefs);
00239     return grad(i, coefs);
00240     }
00241 
00242     Real eval(const Coord& x) const
00243     {
00244     Real d;
00245     if (inGrid(x))
00246     {
00247         d = interp(x);
00248     }
00249     else
00250     {
00251         Coord xclamp = clamp(x);
00252         d = interp(xclamp);
00253         d = helper::rsqrt((x-xclamp).norm2() + d*d); // we underestimate the distance
00254     }
00255     return d;
00256     }
00257 
00258     Real quickeval(const Coord& x) const
00259     {
00260     Real d;
00261     if (inGrid(x))
00262     {
00263         d = dists[index(x)] - cellWidth[0]; // we underestimate the distance
00264     }
00265     else
00266     {
00267         Coord xclamp = clamp(x);
00268         d = dists[index(xclamp)] - cellWidth[0]; // we underestimate the distance
00269         d = helper::rsqrt((x-xclamp).norm2() + d*d);
00270     }
00271     return d;
00272     }
00273 
00274     Real eval2(const Coord& x) const
00275     {
00276     Real d2;
00277     if (inGrid(x))
00278     {
00279         Real d = interp(x);
00280         d2 = d*d;
00281     }
00282     else
00283     {
00284         Coord xclamp = clamp(x);
00285         Real d = interp(xclamp);
00286         d2 = ((x-xclamp).norm2() + d*d); // we underestimate the distance
00287     }
00288     return d2;
00289     }
00290 
00291     Real quickeval2(const Coord& x) const
00292     {
00293     Real d2;
00294     if (inGrid(x))
00295     {
00296         Real d = dists[index(x)] - cellWidth[0]; // we underestimate the distance
00297         d2 = d*d;
00298     }
00299     else
00300     {
00301         Coord xclamp = clamp(x);
00302         Real d = dists[index(xclamp)] - cellWidth[0]; // we underestimate the distance
00303         d2 = ((x-xclamp).norm2() + d*d);
00304     }
00305     return d2;
00306     }
00307 
00308     //CudaVector<SamplingPoint> meshPts;
00309     CudaVector<Coord> meshPts;
00310     sofa::core::componentmodel::topology::BaseMeshTopology::SeqTriangles meshTriangles;
00311     sofa::core::componentmodel::topology::BaseMeshTopology::SeqQuads meshQuads;
00312 
00313 protected:
00314     int nbRef;
00315     VecReal dists;
00316     const int nx,ny,nz, nxny, nxnynz;
00317     const Coord pmin, pmax;
00318     const Coord cellWidth, invCellWidth;
00319     Coord bbmin, bbmax; 
00320 
00321     Real cubeDim; 
00322     //bool updated;
00323 
00324     // Grid shared resources
00325 
00326     struct CudaDistanceGridParams
00327     {
00328         std::string filename;
00329         double scale;
00330     int nx,ny,nz;
00331     Coord pmin,pmax;
00332     bool operator==(const CudaDistanceGridParams& v) const
00333     {
00334         if (!(filename == v.filename)) return false;
00335         if (!(scale    == v.scale   )) return false;
00336         if (!(nx       == v.nx      )) return false;
00337         if (!(ny       == v.ny      )) return false;
00338         if (!(nz       == v.nz      )) return false;
00339         if (!(pmin[0]  == v.pmin[0] )) return false;
00340         if (!(pmin[1]  == v.pmin[1] )) return false;
00341         if (!(pmin[2]  == v.pmin[2] )) return false;
00342         if (!(pmax[0]  == v.pmax[0] )) return false;
00343         if (!(pmax[1]  == v.pmax[1] )) return false;
00344         if (!(pmax[2]  == v.pmax[2] )) return false;
00345         return true;
00346     }
00347     bool operator<(const CudaDistanceGridParams& v) const
00348     {
00349         if (filename < v.filename) return true;
00350         if (filename > v.filename) return false;
00351         if (scale    < v.scale   ) return true;
00352         if (scale    > v.scale   ) return false;
00353         if (nx       < v.nx      ) return false;
00354         if (nx       > v.nx      ) return true;
00355         if (ny       < v.ny      ) return false;
00356         if (ny       > v.ny      ) return true;
00357         if (nz       < v.nz      ) return false;
00358         if (nz       > v.nz      ) return true;
00359         if (pmin[0]  < v.pmin[0] ) return false;
00360         if (pmin[0]  > v.pmin[0] ) return true;
00361         if (pmin[1]  < v.pmin[1] ) return false;
00362         if (pmin[1]  > v.pmin[1] ) return true;
00363         if (pmin[2]  < v.pmin[2] ) return false;
00364         if (pmin[2]  > v.pmin[2] ) return true;
00365         if (pmax[0]  < v.pmax[0] ) return false;
00366         if (pmax[0]  > v.pmax[0] ) return true;
00367         if (pmax[1]  < v.pmax[1] ) return false;
00368         if (pmax[1]  > v.pmax[1] ) return true;
00369         if (pmax[2]  < v.pmax[2] ) return false;
00370         if (pmax[2]  > v.pmax[2] ) return true;
00371         return false;
00372     }
00373     bool operator>(const CudaDistanceGridParams& v) const
00374     {
00375         if (filename > v.filename) return true;
00376         if (filename < v.filename) return false;
00377         if (scale    > v.scale   ) return true;
00378         if (scale    < v.scale   ) return false;
00379         if (nx       > v.nx      ) return false;
00380         if (nx       < v.nx      ) return true;
00381         if (ny       > v.ny      ) return false;
00382         if (ny       < v.ny      ) return true;
00383         if (nz       > v.nz      ) return false;
00384         if (nz       < v.nz      ) return true;
00385         if (pmin[0]  > v.pmin[0] ) return false;
00386         if (pmin[0]  < v.pmin[0] ) return true;
00387         if (pmin[1]  > v.pmin[1] ) return false;
00388         if (pmin[1]  < v.pmin[1] ) return true;
00389         if (pmin[2]  > v.pmin[2] ) return false;
00390         if (pmin[2]  < v.pmin[2] ) return true;
00391         if (pmax[0]  > v.pmax[0] ) return false;
00392         if (pmax[0]  < v.pmax[0] ) return true;
00393         if (pmax[1]  > v.pmax[1] ) return false;
00394         if (pmax[1]  < v.pmax[1] ) return true;
00395         if (pmax[2]  > v.pmax[2] ) return false;
00396         if (pmax[2]  < v.pmax[2] ) return true;
00397         return false;
00398     }
00399     };
00400     static std::map<CudaDistanceGridParams, CudaDistanceGrid*>& getShared();
00401 
00402 };
00406 
00407 class CudaRigidDistanceGridCollisionModel;
00408 
00409 class CudaRigidDistanceGridCollisionElement : public core::TCollisionElementIterator<CudaRigidDistanceGridCollisionModel>
00410 {
00411 public:
00412     CudaRigidDistanceGridCollisionElement(CudaRigidDistanceGridCollisionModel* model, int index);
00413 
00414     explicit CudaRigidDistanceGridCollisionElement(const core::CollisionElementIterator& i);
00415 
00416     CudaDistanceGrid* getGrid();
00417 
00418     bool isTransformed();
00419     const Matrix3& getRotation();
00420     const Vector3& getTranslation();
00421 
00422     void setGrid(CudaDistanceGrid* surf);
00423 
00427     CudaDistanceGrid* getPrevGrid();
00428     const Matrix3& getPrevRotation();
00429     const Vector3& getPrevTranslation();
00430     double getPrevDt();
00432     
00434     void setNewState(double dt, CudaDistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00435 };
00436 
00437 class CudaRigidDistanceGridCollisionModel : public core::CollisionModel
00438 {
00439 protected:
00440 
00441     class ElementData
00442     {
00443     public:
00444         Matrix3 rotation;
00445         Vector3 translation;
00446         CudaDistanceGrid* grid;
00447         
00451         CudaDistanceGrid* prevGrid; 
00452         Matrix3 prevRotation; 
00453         Vector3 prevTranslation; 
00454         double prevDt; 
00455 
00456         
00457         bool isTransformed; 
00458         ElementData() : grid(NULL), prevGrid(NULL), prevDt(0.0), isTransformed(false) { rotation.identity(); prevRotation.identity(); }
00459     };
00460 
00461     std::vector<ElementData> elems;
00462     bool modified;
00463 
00464     // Input data parameters
00465     Data< std::string > filename;
00466     Data< double > scale;
00467     Data< helper::fixed_array<CudaDistanceGrid::Coord,2> > box;
00468     Data< int > nx;
00469     Data< int > ny;
00470     Data< int > nz;
00471     Data< std::string > dumpfilename;
00472 
00473     core::componentmodel::behavior::MechanicalState<RigidTypes>* rigid;
00474 
00475     void updateGrid();
00476 public:
00477     typedef Rigid3Types InDataTypes;
00478     typedef Vec3Types DataTypes;
00479     typedef CudaRigidDistanceGridCollisionElement Element;
00480 
00481     Data< bool > usePoints;
00482 
00483     CudaRigidDistanceGridCollisionModel();
00484 
00485     ~CudaRigidDistanceGridCollisionModel();
00486 
00487     core::componentmodel::behavior::MechanicalState<InDataTypes>* getRigidModel() { return rigid; }
00488     core::componentmodel::behavior::MechanicalState<InDataTypes>* getMechanicalState() { return rigid; }
00489 
00490     void init();
00491 
00492     CudaDistanceGrid* getGrid(int index=0)
00493     {
00494         return elems[index].grid;
00495     }
00496     bool isTransformed(int index=0)
00497     {
00498         return elems[index].isTransformed;
00499     }
00500     const Matrix3& getRotation(int index=0)
00501     {
00502         return elems[index].rotation;
00503     }
00504     const Vector3& getTranslation(int index=0)
00505     {
00506         return elems[index].translation;
00507     }
00508 
00509     void setGrid(CudaDistanceGrid* surf, int index=0);
00510 
00511     CudaDistanceGrid* getPrevGrid(int index=0)
00512     {
00513         return elems[index].prevGrid;
00514     }
00515     const Matrix3& getPrevRotation(int index=0)
00516     {
00517         return elems[index].prevRotation;
00518     }
00519     const Vector3& getPrevTranslation(int index=0)
00520     {
00521         return elems[index].prevTranslation;
00522     }
00523     double getPrevDt(int index=0)
00524     {
00525         return elems[index].prevDt;
00526     }
00527     
00529     void setNewState(int index, double dt, CudaDistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00530     
00532     
00534     void setNewState(double dt, CudaDistanceGrid* grid, const Matrix3& rotation, const Vector3& translation);
00535 
00536     // -- CollisionModel interface
00537 
00538     void resize(int size);
00539 
00541     void computeBoundingTree(int maxDepth=0);
00542 
00543     void draw(int index);
00544 
00545     void draw();
00546 };
00547 
00548 inline CudaRigidDistanceGridCollisionElement::CudaRigidDistanceGridCollisionElement(CudaRigidDistanceGridCollisionModel* model, int index)
00549 : core::TCollisionElementIterator<CudaRigidDistanceGridCollisionModel>(model, index)
00550 {}
00551 
00552 inline CudaRigidDistanceGridCollisionElement::CudaRigidDistanceGridCollisionElement(const core::CollisionElementIterator& i)
00553 : core::TCollisionElementIterator<CudaRigidDistanceGridCollisionModel>(static_cast<CudaRigidDistanceGridCollisionModel*>(i.getCollisionModel()), i.getIndex())
00554 {
00555 }
00556 
00557 inline CudaDistanceGrid* CudaRigidDistanceGridCollisionElement::getGrid() { return model->getGrid(index); }
00558 inline void CudaRigidDistanceGridCollisionElement::setGrid(CudaDistanceGrid* surf) { return model->setGrid(surf, index); }
00559 
00560 inline bool CudaRigidDistanceGridCollisionElement::isTransformed() { return model->isTransformed(index); }
00561 inline const Matrix3& CudaRigidDistanceGridCollisionElement::getRotation() { return model->getRotation(index); }
00562 inline const Vector3& CudaRigidDistanceGridCollisionElement::getTranslation() { return model->getTranslation(index); }
00563 
00564 inline CudaDistanceGrid* CudaRigidDistanceGridCollisionElement::getPrevGrid() { return model->getPrevGrid(index); }
00565 inline const Matrix3& CudaRigidDistanceGridCollisionElement::getPrevRotation() { return model->getPrevRotation(index); }
00566 inline const Vector3& CudaRigidDistanceGridCollisionElement::getPrevTranslation() { return model->getPrevTranslation(index); }
00567 inline double CudaRigidDistanceGridCollisionElement::getPrevDt() { return model->getPrevDt(index); }
00568 
00569 inline void CudaRigidDistanceGridCollisionElement::setNewState(double dt, CudaDistanceGrid* grid, const Matrix3& rotation, const Vector3& translation)
00570 {
00571     return model->setNewState(dt, grid, rotation, translation);
00572 }
00573 
00574 } // namespace cuda
00575 
00576 } // namespace gpu
00577 
00578 } // namespace sofa
00579 
00580 #endif

Generated on Sun Nov 23 03:58:24 2008 for Sofa by  doxygen 1.5.7.1