PointModel.cpp

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 #include <sofa/helper/system/config.h>
00026 #include <sofa/component/collision/proximity.h>
00027 #include <sofa/defaulttype/Mat.h>
00028 #include <sofa/defaulttype/Vec.h>
00029 #include <sofa/core/componentmodel/collision/Intersection.inl>
00030 #include <iostream>
00031 #include <algorithm>
00032 
00033 
00034 
00035 
00036 #include <sofa/component/collision/PointModel.h>
00037 #include <sofa/component/collision/CubeModel.h>
00038 #include <sofa/core/ObjectFactory.h>
00039 #include <vector>
00040 #include <sofa/helper/system/gl.h>
00041 #include <sofa/helper/gl/template.h>
00042 #include <sofa/core/componentmodel/collision/Intersection.inl>
00043 
00044 #include <sofa/core/componentmodel/topology/BaseMeshTopology.h>
00045 
00046 namespace sofa
00047 {
00048 
00049 namespace component
00050 {
00051 
00052 namespace collision
00053 {
00054 
00055 using namespace sofa::defaulttype;
00056 using namespace sofa::core::componentmodel::collision;
00057 using namespace helper;
00058 
00059 SOFA_DECL_CLASS(Point)
00060 
00061 int PointModelClass = core::RegisterObject("Collision model which represents a set of points")
00062 .add< PointModel >()
00063 .addAlias("Point")
00064 // .addAlias("PointModel")
00065 .addAlias("PointMesh")
00066 .addAlias("PointSet")
00067 ;
00068 
00069 PointModel::PointModel()
00070 : mstate(NULL)
00071 , computeNormals( initData(&computeNormals, false, "computeNormals", "activate computation of normal vectors (required for some collision detection algorithms)") )
00072 {
00073 }
00074 
00075 void PointModel::resize(int size)
00076 {
00077     this->core::CollisionModel::resize(size);
00078 }
00079 
00080 void PointModel::init()
00081 {
00082     this->CollisionModel::init();
00083     mstate = dynamic_cast< core::componentmodel::behavior::MechanicalState<Vec3Types>* > (getContext()->getMechanicalState());
00084 
00085     if (mstate==NULL)
00086     {
00087         std::cerr << "ERROR: PointModel requires a Vec3 Mechanical Model.\n";
00088         return;
00089     }
00090 
00091     const int npoints = mstate->getX()->size();
00092     resize(npoints);
00093     if (computeNormals.getValue()) updateNormals();
00094 }
00095 
00096 void PointModel::draw(int index)
00097 {
00098     Point t(this,index);
00099     glBegin(GL_POINTS);
00100     helper::gl::glVertexT(t.p());
00101     glEnd();
00102     if ((unsigned)index < normals.size())
00103     {
00104         glBegin(GL_LINES);
00105         helper::gl::glVertexT(t.p());
00106         helper::gl::glVertexT(t.p()+normals[index]*0.1f);
00107         glEnd();
00108     }
00109 }
00110 
00111 void PointModel::draw()
00112 {
00113     if (getContext()->getShowCollisionModels())
00114     {
00115         if (getContext()->getShowWireFrame())
00116             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00117 
00118         glDisable(GL_LIGHTING);
00119         glPointSize(3);
00120         glColor4fv(getColor4f());
00121 
00122         // Check topological modifications
00123         const int npoints = mstate->getX()->size();
00124         if (npoints != size)
00125         {
00126             resize(npoints);
00127         }
00128 
00129         for (int i = 0; i < size; i++)
00130         {
00131             draw(i);
00132         }
00133 
00134         glColor3f(1.0f, 1.0f, 1.0f);
00135         glDisable(GL_LIGHTING);
00136         glPointSize(1);
00137         if (getContext()->getShowWireFrame())
00138             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00139     }
00140     if (getPrevious()!=NULL && getContext()->getShowBoundingCollisionModels())
00141         getPrevious()->draw();
00142 }
00143 
00144 bool PointModel::canCollideWithElement(int index, CollisionModel* model2, int index2)
00145 {
00146     if (!this->bSelfCollision.getValue()) return true;
00147     if (this->getContext() != model2->getContext()) return true;
00148     if (model2 == this)
00149     {
00150         //std::cout << "point self test "<<index<<" - "<<index2<<std::endl;
00151         return index < index2-2; // || index > index2+1;
00152     }
00153     else
00154         return model2->canCollideWithElement(index2, this, index);
00155 }
00156     
00157 void PointModel::computeBoundingTree(int maxDepth)
00158 {
00159     CubeModel* cubeModel = createPrevious<CubeModel>();
00160     const int npoints = mstate->getX()->size();
00161     bool updated = false;
00162     if (npoints != size)
00163     {
00164         resize(npoints);
00165         updated = true;
00166     }
00167     if (updated) cubeModel->resize(0);
00168     if (!isMoving() && !cubeModel->empty() && !updated) return; // No need to recompute BBox if immobile
00169 
00170     if (computeNormals.getValue()) updateNormals();
00171     
00172     cubeModel->resize(size);
00173     if (!empty())
00174     {
00175         //VecCoord& x = *mstate->getX();
00176         for (int i=0;i<size;i++)
00177         {
00178             Point p(this,i);
00179             const Vector3& pt = p.p();
00180             cubeModel->setParentOf(i, pt, pt);
00181         }
00182         cubeModel->computeBoundingTree(maxDepth);
00183     }
00184 }
00185 
00186 void PointModel::computeContinuousBoundingTree(double dt, int maxDepth)
00187 {
00188     CubeModel* cubeModel = createPrevious<CubeModel>();
00189     const int npoints = mstate->getX()->size();
00190     bool updated = false;
00191     if (npoints != size)
00192     {
00193         resize(npoints);
00194         updated = true;
00195     }
00196     if (!isMoving() && !cubeModel->empty() && !updated) return; // No need to recompute BBox if immobile
00197     
00198     if (computeNormals.getValue()) updateNormals();
00199 
00200     Vector3 minElem, maxElem;
00201 
00202     cubeModel->resize(size);
00203     if (!empty())
00204     {
00205         //VecCoord& x = *mstate->getX();
00206         //VecDeriv& v = *mstate->getV();
00207         for (int i=0;i<size;i++)
00208         {
00209             Point p(this,i);
00210             const Vector3& pt = p.p();
00211             const Vector3 ptv = pt + p.v()*dt;
00212         
00213             for (int c = 0; c < 3; c++)
00214             {
00215                                               minElem[c] = pt[c];
00216                                               maxElem[c] = pt[c];
00217                      if (ptv[c] > maxElem[c]) maxElem[c] = ptv[c];
00218                 else if (ptv[c] < minElem[c]) minElem[c] = ptv[c];
00219             }
00220             cubeModel->setParentOf(i, minElem, maxElem);
00221         }
00222         cubeModel->computeBoundingTree(maxDepth);
00223     }
00224 }
00225     
00226 void PointModel::updateNormals()
00227 {
00228     const VecCoord& x = *mstate->getX();
00229     int n = x.size();
00230     normals.resize(n);
00231     for (int i=0;i<n;++i)
00232     {
00233         normals[i].clear();
00234     }
00235     core::componentmodel::topology::BaseMeshTopology* mesh = getContext()->getMeshTopology();
00236     if (mesh->getNbTetras()+mesh->getNbHexas() > 0)
00237     {
00238         if (mesh->getNbTetras()>0)
00239         {
00240             const core::componentmodel::topology::BaseMeshTopology::SeqTetras &elems = mesh->getTetras();
00241             for (unsigned int i=0; i < elems.size(); ++i)
00242             {
00243                 const core::componentmodel::topology::BaseMeshTopology::Tetra &e = elems[i];
00244                 const Coord& p1 = x[e[0]];
00245                 const Coord& p2 = x[e[1]];
00246                 const Coord& p3 = x[e[2]];
00247                 const Coord& p4 = x[e[3]];
00248                 Coord& n1 = normals[e[0]];
00249                 Coord& n2 = normals[e[1]];
00250                 Coord& n3 = normals[e[2]];
00251                 Coord& n4 = normals[e[3]];
00252                 Coord n;
00253                 n = cross(p3-p1,p2-p1); n.normalize();
00254                 n1 += n;
00255                 n2 += n;
00256                 n3 += n;
00257                 n = cross(p4-p1,p3-p1); n.normalize();
00258                 n1 += n;
00259                 n3 += n;
00260                 n4 += n;
00261                 n = cross(p2-p1,p4-p1); n.normalize();
00262                 n1 += n;
00263                 n4 += n;
00264                 n2 += n;
00265                 n = cross(p3-p2,p4-p2); n.normalize();
00266                 n2 += n;
00267                 n4 += n;
00268                 n3 += n;
00269             }
00270         }
00272     }
00273     else if (mesh->getNbTriangles()+mesh->getNbQuads() > 0)
00274     {
00275         if (mesh->getNbTriangles()>0)
00276         {
00277             const core::componentmodel::topology::BaseMeshTopology::SeqTriangles &elems = mesh->getTriangles();
00278             for (unsigned int i=0; i < elems.size(); ++i)
00279             {
00280                 const core::componentmodel::topology::BaseMeshTopology::Triangle &e = elems[i];
00281                 const Coord& p1 = x[e[0]];
00282                 const Coord& p2 = x[e[1]];
00283                 const Coord& p3 = x[e[2]];
00284                 Coord& n1 = normals[e[0]];
00285                 Coord& n2 = normals[e[1]];
00286                 Coord& n3 = normals[e[2]];
00287                 Coord n;
00288                 n = cross(p2-p1,p3-p1); n.normalize();
00289                 n1 += n;
00290                 n2 += n;
00291                 n3 += n;
00292             }
00293         }
00294         if (mesh->getNbQuads()>0)
00295         {
00296             const core::componentmodel::topology::BaseMeshTopology::SeqQuads &elems = mesh->getQuads();
00297             for (unsigned int i=0; i < elems.size(); ++i)
00298             {
00299                 const core::componentmodel::topology::BaseMeshTopology::Quad &e = elems[i];
00300                 const Coord& p1 = x[e[0]];
00301                 const Coord& p2 = x[e[1]];
00302                 const Coord& p3 = x[e[2]];
00303                 const Coord& p4 = x[e[3]];
00304                 Coord& n1 = normals[e[0]];
00305                 Coord& n2 = normals[e[1]];
00306                 Coord& n3 = normals[e[2]];
00307                 Coord& n4 = normals[e[3]];
00308                 Coord n;
00309                 n = cross(p3-p1,p4-p2); n.normalize();
00310                 n1 += n;
00311                 n2 += n;
00312                 n3 += n;
00313                 n4 += n;
00314             }
00315         }
00316     }
00317     for (int i=0;i<n;++i)
00318     {
00319         SReal l = normals[i].norm();
00320         if (l > 1.0e-3)
00321             normals[i] *= 1/l;
00322         else
00323             normals[i].clear();
00324     }
00325 }
00326 
00327 
00328 bool Point::testLMD(const Vector3 &PQ, double &coneFactor, double &coneExtension)
00329 {
00330     Vector3 pt = p();
00331 
00332     sofa::core::componentmodel::topology::BaseMeshTopology* mesh = model->getMeshTopology();
00333     helper::vector<Vector3> x = (*model->mstate->getX());
00334 
00335     const helper::vector <unsigned int>& triangleVertexShell = mesh->getTriangleVertexShell(index);
00336     const helper::vector <unsigned int>& edgeVertexShell = mesh->getEdgeVertexShell(index);
00337 
00338 
00339     Vector3 nMean;
00340 
00341     for (unsigned int i=0; i<triangleVertexShell.size(); i++)
00342     {
00343         unsigned int t = triangleVertexShell[i];
00344         const fixed_array<unsigned int,3>& ptr = mesh->getTriangle(t);
00345         Vector3 nCur = (x[ptr[1]]-x[ptr[0]]).cross(x[ptr[2]]-x[ptr[0]]);
00346         nCur.normalize();
00347         nMean += nCur;
00348     }
00349 
00350     if (triangleVertexShell.size()==0)
00351     {
00352         for (unsigned int i=0; i<edgeVertexShell.size(); i++)
00353         {
00354             unsigned int e = edgeVertexShell[i];
00355             const fixed_array<unsigned int,2>& ped = mesh->getEdge(e);
00356             Vector3 l = (pt - x[ped[0]]) + (pt - x[ped[1]]);
00357             l.normalize();
00358             nMean += l;
00359         }       
00360     }
00361 
00362     if (nMean.norm()> 0.0000000001)
00363         nMean.normalize();
00364         
00365 
00366     for (unsigned int i=0; i<edgeVertexShell.size(); i++)
00367     {
00368         unsigned int e = edgeVertexShell[i];
00369         const fixed_array<unsigned int,2>& ped = mesh->getEdge(e);
00370         Vector3 l = (pt - x[ped[0]]) + (pt - x[ped[1]]);
00371         l.normalize();
00372         double computedAngleCone = dot(nMean , l) * coneFactor;
00373         if (computedAngleCone<0)
00374             computedAngleCone=0.0;
00375         computedAngleCone+=coneExtension;
00376         if (dot(l , PQ) < -computedAngleCone*PQ.norm())
00377             return false;
00378     }
00379     return true;
00380 
00381 
00382 }
00383 
00384 
00385 
00386 
00387 
00388 
00389 
00390         
00391 } // namespace collision
00392 
00393 } // namespace component
00394 
00395 } // namespace sofa
00396 

Generated on Sun Nov 23 02:34:30 2008 for Sofa by  doxygen 1.5.7.1