LineModel.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/component/collision/LineModel.h>
00026 #include <sofa/component/collision/CubeModel.h>
00027 #include <sofa/component/collision/Line.h>
00028 #include <sofa/core/CollisionElement.h>
00029 #include <sofa/core/ObjectFactory.h>
00030 #include <vector>
00031 #include <sofa/helper/gl/template.h>
00032 #include <sofa/simulation/tree/GNode.h>
00033 #include <sofa/component/topology/PointSetTopologyChange.h>
00034 #include <sofa/component/topology/EdgeSetTopologyChange.h>
00035 
00036 namespace sofa
00037 {
00038 
00039 namespace component
00040 {
00041 
00042 namespace collision
00043 {
00044 
00045 SOFA_DECL_CLASS(Line)
00046 
00047 int LineModelClass = core::RegisterObject("collision model using a linear mesh, as described in MeshTopology")
00048 .add< LineModel >()
00049 .addAlias("Line")
00050 .addAlias("LineMeshModel")
00051 .addAlias("LineSetModel")
00052 .addAlias("LineMesh")
00053 .addAlias("LineSet")
00054 ;
00055 
00056 using core::componentmodel::topology::BaseMeshTopology;
00057 
00058 //int LineSetModelClass = core::RegisterObject("collision model using a linear mesh, as described in MeshTopology")
00059 //.add< LineSetModel >()
00060 //;
00061 
00062 LineModel::LineModel()
00063 : mstate(NULL), topology(NULL), meshRevision(-1)
00064 {
00065 }
00066 
00067 //LineMeshModel::LineMeshModel()
00068 //: meshRevision(-1), mesh(NULL)
00069 //{
00070 //}
00071 
00072 //LineSetModel::LineSetModel()
00073 //: mesh(NULL)
00074 //{
00075 //}
00076 
00077 void LineModel::resize(int size)
00078 {
00079     this->core::CollisionModel::resize(size);
00080     elems.resize(size);
00081 }
00082 
00083 void LineModel::init()
00084 {
00085     this->CollisionModel::init();
00086     mstate = dynamic_cast< core::componentmodel::behavior::MechanicalState<Vec3Types>* > (getContext()->getMechanicalState());
00087     mpoints = getContext()->get<PointModel>();
00088 
00089     if (mstate==NULL)
00090     {
00091         std::cerr << "ERROR: LineModel requires a Vec3 Mechanical Model.\n";
00092         return;
00093     }
00094 
00095     core::componentmodel::topology::BaseMeshTopology *bmt = getContext()->getMeshTopology();
00096     if (!bmt) {
00097         std::cerr << "ERROR: LineModel requires a MeshTopology.\n";
00098         return;
00099     }
00100     
00101     resize( bmt->getNbEdges() );
00102 
00103     for(int i = 0; i < bmt->getNbEdges(); i++)
00104     {
00105         elems[i].i1 = bmt->getEdge(i)[0];
00106         elems[i].i2 = bmt->getEdge(i)[1];
00107     }       
00108     
00109     updateFromTopology();
00110 }
00111 
00112 
00113 void LineModel::handleTopologyChange()
00114 {
00115     //if (edges != &myedges)
00116     //{
00117         // We use the same edge array as the topology -> only resize and recompute flags
00118 
00119     core::componentmodel::topology::BaseMeshTopology *bmt = getContext()->getMeshTopology();
00120     if (bmt)
00121     {
00122         resize(bmt->getNbEdges());
00123 
00124         for(int i = 0; i < bmt->getNbEdges(); i++)
00125         {
00126             elems[i].i1 = bmt->getEdge(i)[0];
00127             elems[i].i2 = bmt->getEdge(i)[1];
00128         }
00129 
00130         needsUpdate = true;
00131     }
00132   
00133     //  return;
00134     //}
00135     
00136     if (bmt)
00137     {
00138         std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itBegin = bmt->firstChange();
00139         std::list<const sofa::core::componentmodel::topology::TopologyChange *>::const_iterator itEnd = bmt->lastChange();
00140 
00141         while( itBegin != itEnd )
00142         {
00143             core::componentmodel::topology::TopologyChangeType changeType = (*itBegin)->getChangeType();
00144 
00145             switch( changeType ) 
00146             {   
00147                 case core::componentmodel::topology::ENDING_EVENT :
00148                 {
00149                 //  std::cout << "INFO_print : Col - ENDING_EVENT" << std::endl;
00150                     needsUpdate = true;                 
00151                     break;
00152                 }
00153                 
00154 
00155                 case core::componentmodel::topology::EDGESADDED :
00156                 {
00157                 //  std::cout << "INFO_print : Col - EDGESADDED" << std::endl;
00158                     const sofa::component::topology::EdgesAdded *ta = static_cast< const sofa::component::topology::EdgesAdded * >( *itBegin );
00159                     
00160                     for (unsigned int i = 0; i < ta->getNbAddedEdges(); ++i) 
00161                     {                           
00162                         elems[elems.size() - ta->getNbAddedEdges() + i].i1 = (ta->edgeArray[i])[0];   
00163                         elems[elems.size() - ta->getNbAddedEdges() + i].i2 = (ta->edgeArray[i])[1];   
00164                     }
00165 
00166                     resize( elems.size() );                             
00167                     needsUpdate = true;
00168                                             
00169                     break;
00170                 }
00171 
00172                 case core::componentmodel::topology::EDGESREMOVED :
00173                 {
00174                     //std::cout << "INFO_print : Col - EDGESREMOVED" << std::endl;
00175                     unsigned int last;
00176                     unsigned int ind_last;                          
00177                     
00178                     if (bmt)
00179                     {
00180                         last = bmt->getNbEdges() - 1;
00181                     }
00182                     else
00183                     {
00184                         last = elems.size() -1;
00185                     }
00186 
00187                     const sofa::helper::vector< unsigned int > &tab = ( static_cast< const sofa::component::topology::EdgesRemoved *>( *itBegin ) )->getArray();
00188                     
00189                     LineData tmp;
00190                     //topology::Edge tmp2;          
00191 
00192                     for (unsigned int i = 0; i < tab.size(); ++i)
00193                     {
00194                         unsigned int ind_k = tab[i];                                                        
00195 
00196                         tmp = elems[ind_k];
00197                         elems[ind_k] = elems[last];
00198                         elems[last] = tmp;
00199                                   
00200                         //std::cout << "INFO_print : Col - myedges.size() = " << myedges.size() << std::endl;
00201                         //std::cout << "INFO_print : Col - ind_k = " << ind_k << std::endl;
00202                         //std::cout << "INFO_print : Col - last = " << last << std::endl;
00203 
00204                         //tmp2 = myedges[ind_k];
00205                         //myedges[ind_k] = myedges[last];
00206                         //myedges[last] = tmp2;
00207                                                                 
00208                         ind_last = elems.size() - 1;
00209 
00210                         if(last != ind_last)
00211                         {
00212                             tmp = elems[last];
00213                             elems[last] = elems[ind_last];
00214                             elems[ind_last] = tmp;
00215                               
00216                               //tmp2 = myedges[last];
00217                               //myedges[last] = myedges[ind_last];
00218                               //myedges[ind_last] = tmp2;
00219                         }
00220 
00221                         //myedges.resize( elems.size() - 1 );
00222                         resize( elems.size() - 1 );                         
00223 
00224                         --last;
00225                     }
00226 
00227                     needsUpdate=true;
00228                     
00229                     break;
00230                 }               
00231 
00232                 case core::componentmodel::topology::POINTSREMOVED :
00233                 {   
00234                     //std::cout << "INFO_print : Col - POINTSREMOVED" << std::endl;
00235                     if (bmt)
00236                     {
00237                         unsigned int last = bmt->getNbPoints() - 1;
00238 
00239                         unsigned int i,j;
00240                         const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRemoved * >( *itBegin ) )->getArray();
00241                         
00242                         sofa::helper::vector<unsigned int> lastIndexVec;
00243                         for(unsigned int i_init = 0; i_init < tab.size(); ++i_init)
00244                         {
00245                             lastIndexVec.push_back(last - i_init);
00246                         }
00247                     
00248                         for ( i = 0; i < tab.size(); ++i)
00249                         {
00250                             unsigned int i_next = i;
00251                             bool is_reached = false;
00252                             while( (!is_reached) && (i_next < lastIndexVec.size() - 1))
00253                             {
00254                                 i_next += 1 ;
00255                                 is_reached = is_reached || (lastIndexVec[i_next] == tab[i]);
00256                             }
00257 
00258                             if(is_reached)
00259                             {
00260                                 lastIndexVec[i_next] = lastIndexVec[i];
00261                             }
00262 
00263                             const sofa::helper::vector<unsigned int> &shell = bmt->getEdgeVertexShell(lastIndexVec[i]);
00264                             
00265                             for (j = 0; j < shell.size(); ++j) 
00266                             {
00267                                 unsigned int ind_j = shell[j];
00268 
00269                                 if ((unsigned)elems[ind_j].i1 == last)
00270                                 {
00271                                     elems[ind_j].i1 = tab[i];
00272                                 }
00273                                 else if ((unsigned)elems[ind_j].i2 == last)
00274                                 {
00275                                     elems[ind_j].i2 = tab[i];
00276                                 }
00277                             }
00278 
00279                             --last;
00280                         }                   
00281                     }       
00282             
00283                     needsUpdate=true;
00284                     
00285                     break;
00286                 }
00287 
00288                 case core::componentmodel::topology::POINTSRENUMBERING:
00289                 {   
00290                     //std::cout << "INFO_print : Vis - POINTSRENUMBERING" << std::endl;
00291                     if (bmt)
00292                     {   
00293                         unsigned int i;
00294 
00295                         const sofa::helper::vector<unsigned int> tab = ( static_cast< const sofa::component::topology::PointsRenumbering * >( *itBegin ) )->getinv_IndexArray();
00296 
00297                         for ( i = 0; i < elems.size(); ++i)
00298                         {                                   
00299                             elems[i].i1  = tab[elems[i].i1];
00300                             elems[i].i2  = tab[elems[i].i2];                                    
00301                         }
00302                     }               
00303                     
00304                     break;
00305                 }
00306 
00307                 default:
00308                     // Ignore events that are not Edge  related.
00309                     break;
00310             }; // switch( changeType )
00311             
00312             resize( elems.size() ); // not necessary
00313 
00314             ++itBegin;
00315         } // while( changeIt != last; )
00316     }
00317 }
00318 
00319 void LineModel::updateFromTopology()
00320 {
00321     core::componentmodel::topology::BaseMeshTopology *bmt = getContext()->getMeshTopology();
00322     if (bmt)
00323     {
00324         int revision = bmt->getRevision();
00325         if (revision == meshRevision) 
00326             return;
00327 
00328         needsUpdate = true;
00329 
00330         const unsigned int nbPoints = mstate->getX()->size();
00331         const unsigned int nbLines = bmt->getNbEdges();
00332 
00333         resize( nbLines );
00334         int index = 0;
00335     
00336         for (unsigned int i = 0; i < nbLines; i++)
00337         {
00338             topology::BaseMeshTopology::Line idx = bmt->getEdge(i);
00339         
00340             if (idx[0] >= nbPoints || idx[1] >= nbPoints)
00341             {
00342                 std::cerr << "ERROR: Out of range index in Line " << i << ": " << idx[0] << " " << idx[1] << " ( total points = " << nbPoints << " )\n";
00343                 continue;
00344             }
00345 
00346             elems[index].i1 = idx[0];
00347             elems[index].i2 = idx[1];
00348             ++index;
00349         }
00350 
00351         meshRevision = revision;
00352     }
00353 }
00354 
00355 void LineModel::draw(int index)
00356 {
00357     Line t(this,index);
00358     glBegin(GL_LINES);
00359     helper::gl::glVertexT(t.p1());
00360     helper::gl::glVertexT(t.p2());
00361     glEnd();
00362 }
00363 
00364 void LineModel::draw()
00365 {
00366     if (getContext()->getShowCollisionModels())
00367     {
00368         if (getContext()->getShowWireFrame())
00369             glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
00370 
00371         glDisable(GL_LIGHTING);
00372         glColor4fv(getColor4f()); //glColor3f(0.0f, 0.0f, 1.0f);
00373 
00374         for (int i=0;i<size;i++) //elems.size()
00375         {
00376             if (elems[i].i1 < elems[i].i2) // only display non-edge lines
00377                 draw(i);
00378         }
00379 
00380         glColor3f(1.0f, 1.0f, 1.0f);
00381         glDisable(GL_LIGHTING);
00382         if (getContext()->getShowWireFrame())
00383             glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
00384     }
00385     if (getPrevious()!=NULL && getContext()->getShowBoundingCollisionModels())
00386         getPrevious()->draw();
00387 }
00388     
00389 bool LineModel::canCollideWithElement(int index, CollisionModel* model2, int index2)
00390 {
00391     if (!this->bSelfCollision.getValue()) return true;
00392     if (this->getContext() != model2->getContext()) return true;
00393     if (model2 == this)
00394     {
00395         //std::cout << "line self test "<<index<<" - "<<index2<<std::endl;
00396         return index < index2-2; // || index > index2+1;
00397     }
00398     else if (model2 == mpoints)
00399     {
00400         //std::cout << "line-point self test "<<index<<" - "<<index2<<std::endl;
00401         return index2 < elems[index].i1-1 || index2 > elems[index].i2+1;
00402     }
00403     else
00404         return model2->canCollideWithElement(index2, this, index);
00405 }
00406     
00407 void LineModel::computeBoundingTree(int maxDepth)
00408 {
00409     CubeModel* cubeModel = createPrevious<CubeModel>();
00410     updateFromTopology();
00411     if (needsUpdate) cubeModel->resize(0);
00412     if (!isMoving() && !cubeModel->empty() && !needsUpdate) return; // No need to recompute BBox if immobile
00413 
00414     needsUpdate = false;    
00415     Vector3 minElem, maxElem;
00416     
00417     cubeModel->resize(size);
00418     if (!empty())
00419     {
00420         for (int i=0;i<size;i++)
00421         {
00422             Vector3 minElem, maxElem;
00423             Line l(this,i);
00424             const Vector3& pt1 = l.p1();
00425             const Vector3& pt2 = l.p2();
00426         
00427             for (int c = 0; c < 3; c++)
00428             {
00429                                               minElem[c] = pt1[c];
00430                                               maxElem[c] = pt1[c];
00431                      if (pt2[c] > maxElem[c]) maxElem[c] = pt2[c];
00432                 else if (pt2[c] < minElem[c]) minElem[c] = pt2[c];
00433             }
00434 
00435             cubeModel->setParentOf(i, minElem, maxElem);
00436         }
00437         cubeModel->computeBoundingTree(maxDepth);
00438     }
00439 }
00440 
00441 void LineModel::computeContinuousBoundingTree(double dt, int maxDepth)
00442 {
00443     CubeModel* cubeModel = createPrevious<CubeModel>();
00444     updateFromTopology();
00445     if (needsUpdate) cubeModel->resize(0);
00446     if (!isMoving() && !cubeModel->empty() && !needsUpdate) return; // No need to recompute BBox if immobile
00447 
00448     needsUpdate=false;  
00449     Vector3 minElem, maxElem;
00450 
00451     cubeModel->resize(size);
00452     if (!empty())
00453     {
00454         for (int i=0;i<size;i++)
00455         {
00456             Line t(this,i);
00457             const Vector3& pt1 = t.p1();
00458             const Vector3& pt2 = t.p2();
00459             const Vector3 pt1v = pt1 + t.v1()*dt;
00460             const Vector3 pt2v = pt2 + t.v2()*dt;
00461         
00462             for (int c = 0; c < 3; c++)
00463             {
00464                                               minElem[c] = pt1[c];
00465                                               maxElem[c] = pt1[c];
00466                      if (pt2[c] > maxElem[c]) maxElem[c] = pt2[c];
00467                 else if (pt2[c] < minElem[c]) minElem[c] = pt2[c];
00468 
00469                      if (pt1v[c] > maxElem[c]) maxElem[c] = pt1v[c];
00470                 else if (pt1v[c] < minElem[c]) minElem[c] = pt1v[c];
00471                      if (pt2v[c] > maxElem[c]) maxElem[c] = pt2v[c];
00472                 else if (pt2v[c] < minElem[c]) minElem[c] = pt2v[c];
00473             }
00474             cubeModel->setParentOf(i, minElem, maxElem);
00475         }
00476         cubeModel->computeBoundingTree(maxDepth);
00477     }
00478 }
00479 
00480 } // namespace collision
00481 
00482 } // namespace component
00483 
00484 } // namespace sofa
00485 

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