RayTraceDetection.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 
00026 #include <sofa/component/collision/RayTriangleIntersection.h>
00027 
00028 #include <sofa/component/collision/Sphere.h>
00029 #include <sofa/component/collision/Triangle.h>
00030 #include <sofa/component/collision/TriangleOctreeModel.h>
00031 #include <sofa/component/collision/CubeModel.h>
00032 #include <sofa/component/collision/Line.h>
00033 #include <sofa/component/collision/Point.h>
00034 #include <sofa/helper/FnDispatcher.h>
00035 #include <sofa/core/componentmodel/collision/DetectionOutput.h>
00036 #include <sofa/core/ObjectFactory.h>
00037 #include <sofa/component/collision/RayTraceDetection.h>
00038 #include <sofa/simulation/tree/GNode.h>
00039 #include <map>
00040 #include <queue>
00041 #include <stack>
00042 #include <sofa/helper/system/gl.h>
00043 #include <sofa/helper/system/glut.h>
00044 
00045 #include <sofa/helper/system/thread/CTime.h>
00046 
00047 /* for debugging the collision method */
00048 #ifdef _WIN32
00049 #include <windows.h>
00050 #endif
00051 
00052 namespace sofa
00053 {
00054 
00055   namespace component
00056   {
00057 
00058     namespace collision
00059     {
00060 
00061       using namespace sofa::defaulttype;
00062       using namespace sofa::core::componentmodel::collision;
00063       using namespace collision;
00064       using sofa::helper::system::thread::CTime;
00065       using sofa::helper::system::thread::ctime_t;
00066 
00067         SOFA_DECL_CLASS (RayTraceDetection)
00068     int RayTraceDetectionClass =
00069     core::
00070     RegisterObject
00071     ("Collision detection using extensive pair-wise tests").add <
00072     RayTraceDetection > ();
00073 
00074       using namespace core::objectmodel;
00075 
00076         RayTraceDetection::
00077     RayTraceDetection ():bDraw (initData
00078                   (&bDraw, false, "draw",
00079                    "enable/disable display of results"))
00080       {
00081       }
00082 
00083 
00084       void RayTraceDetection::findPairsVolume (CubeModel * cm1, CubeModel * cm2)
00085       {
00086     /*Obtain the CollisionModel at the lowest level, in this case it must be a TriangleOctreeModel */
00087 
00088     TriangleOctreeModel *tm1 =
00089       dynamic_cast < TriangleOctreeModel * >(cm1->getLast ());
00090     TriangleOctreeModel *tm2 =
00091       dynamic_cast < TriangleOctreeModel * >(cm2->getLast ());
00092     if (!tm1 || !tm2)
00093         return;
00094     
00095 
00096         /*construct the octree of both models, when it still doesn't exisits */
00097     if (!tm1->octreeRoot)
00098       {
00099 
00100         tm1->buildOctree ();
00101       }
00102 
00103     if (!tm2->octreeRoot)
00104       {
00105 
00106         tm2->buildOctree ();
00107 
00108       }
00109 
00110     /* get the output vector for a TriangleOctreeModel, TriangleOctreeModel Collision*/
00111     /*Get the cube representing the bounding box of both Models */
00112     sofa::core::componentmodel::collision::DetectionOutputVector *& contacts=outputsMap[std::make_pair(tm1, tm2)];
00113       
00114 
00115 
00116     if (contacts == NULL)
00117       {
00118         contacts = new
00119           sofa::core::componentmodel::collision::TDetectionOutputVector <
00120           TriangleOctreeModel, TriangleOctreeModel >;
00121 
00122       }
00123 
00124 
00125 
00126 
00127         TDetectionOutputVector < TriangleOctreeModel,
00128       TriangleOctreeModel > *outputs =
00129       static_cast < TDetectionOutputVector < TriangleOctreeModel,
00130       TriangleOctreeModel > *>(contacts);
00131 
00132     Cube cube1 (cm1, 0);
00133     Cube cube2 (cm2, 0);
00134 
00135 
00136     const Vector3 & minVect2 = cube2.minVect ();
00137     const Vector3 & maxVect2 = cube2.maxVect ();
00138     int size = tm1->getSize ();
00139 
00140     for (int j = 0; j < size; j++)
00141       {
00142 
00143         /*creates a Triangle for each object being tested */
00144         Triangle tri1 (tm1, j);
00145 
00146        
00147         /*cosAngle will store the angle between the triangle from t1 and his corresponding in t2 */
00148         double cosAngle;
00149         /*cosAngle will store the angle between the triangle from t1 and another triangle on t1 that is crossed by the -normal of tri1*/
00150         double cosAngle2;
00151         /*resTriangle and resTriangle2 will store the triangle result from the trace method */
00152         int resTriangle = -1;
00153         int resTriangle2 = -1;
00154         Vector3 trianglePoints[4];
00155         bool found = false;
00156         int nPoints = 0;
00157         Vector3 normau[3];
00158         /*if it fails to find a correspondence between the triangles it tries the raytracing procedure */
00159         /*test if this triangle was tested before */
00160 
00161         /*set the triangle as tested */
00162 
00163     
00164         /*test only the points related to this triangle */
00165         if (tri1.flags () & TriangleModel::FLAG_P1)
00166           {
00167         normau[nPoints] = tm1->pNorms[tri1.p1Index ()];
00168         trianglePoints[nPoints++] = tri1.p1 ();
00169 
00170           }
00171         if (tri1.flags () & TriangleModel::FLAG_P2)
00172           {
00173         normau[nPoints] = tm1->pNorms[tri1.p2Index ()];
00174         trianglePoints[nPoints++] = tri1.p2 ();
00175           }
00176         if (tri1.flags () & TriangleModel::FLAG_P3)
00177           {
00178         normau[nPoints] = tm1->pNorms[tri1.p3Index ()];
00179         trianglePoints[nPoints++] = tri1.p3 ();
00180           }
00181 
00182         for (int t = 0; t < nPoints; t++)
00183           {
00184 
00185         Vector3 point = trianglePoints[t];
00186         
00187              if ((point[0] < (minVect2[0]))
00188                  || (point[0] > maxVect2[0] )
00189                  || (point[1] < minVect2[1] )
00190                  || (point[1] > maxVect2[1] )
00191                  || (point[2] < minVect2[2] )
00192                  || (point[2] > maxVect2[2] ))
00193                continue;
00194             /*res and res2 will store the point of intercection and the distance from the point */
00195         TriangleOctree::traceResult res, res2;
00196         /*search a triangle on t2 */
00197         resTriangle =
00198           tm2->octreeRoot->
00199           trace (point /*+ normau[t] * (contactDistance / 2) */ ,
00200              -normau[t], res);
00201         if (resTriangle == -1)
00202           continue;
00203         Triangle triang2 (tm2, resTriangle);
00204         cosAngle = dot (tri1.n (), triang2.n ());
00205         if (cosAngle > 0)
00206           continue;
00207         /*search a triangle on t1, to be sure that the triangle found on t2 isn't outside the t1 object */
00208 
00209         /*if there is no triangle in t1  that is crossed by the tri1 normal (resTriangle2==-1), it means that t1 is not an object with a closed volume, so we can't continue.
00210            If the distance from the  point to the triangle on t1 is less than the distance to the triangle on t2 it means that the corresponding point is outside t1, and is not a good point */
00211         resTriangle2 =
00212           tm1->octreeRoot->trace (point, -normau[t], res2);
00213 
00214 
00215 
00216         if (resTriangle2 == -1 || res2.t < res.t)
00217           {
00218 
00219             continue;
00220           }
00221 
00222         
00223         Triangle tri3 (tm1, resTriangle2);
00224         cosAngle2 = dot (tri1.n (), tri3.n ());
00225         if (cosAngle2 > 0)
00226           continue;
00227 
00228         Vector3 Q =
00229           (triang2.p1 () * (1.0 - res.u - res.v)) +
00230           (triang2.p2 () * res.u) + (triang2.p3 () * res.v);
00231 
00232         outputs->resize (outputs->size () + 1);
00233         DetectionOutput *detection = &*(outputs->end () - 1);
00234 
00235 
00236         detection->elem =
00237           std::pair <
00238           core::CollisionElementIterator,
00239           core::CollisionElementIterator > (tri1, triang2);
00240         detection->point[0] = point;
00241 
00242         detection->point[1] = Q;
00243 
00244         detection->normal = normau[t];
00245 
00246         detection->value = -(res.t);
00247 
00248         detection->id = tri1.getIndex()*3+t;
00249         found = true;
00250 
00251           }
00252 
00253       }
00254 
00255       }
00256 
00257       void RayTraceDetection::addCollisionModel (core::CollisionModel * cm)
00258       {
00259     if (cm->empty ())
00260       return;
00261     for (sofa::helper::vector < core::CollisionModel * >::iterator it =
00262          collisionModels.begin (); it != collisionModels.end (); ++it)
00263       {
00264         core::CollisionModel * cm2 = *it;
00265         if (!cm->isSimulated() && !cm2->isSimulated())
00266           continue;
00267         if (!cm->canCollideWith (cm2))
00268           continue;
00269 
00270               bool swapModels = false;
00271               core::componentmodel::collision::ElementIntersector* intersector = intersectionMethod->findIntersector(cm, cm2, swapModels);
00272               if (intersector == NULL)
00273                   continue;
00274               
00275               core::CollisionModel* cm1 = (swapModels?cm2:cm);
00276               cm2 = (swapModels?cm:cm2);
00277               
00278        
00279         // Here we assume a single root element is present in both models
00280         if (intersector->canIntersect (cm1->begin (), cm2->begin ()))
00281           {
00282 
00283         cmPairs.push_back (std::make_pair (cm1, cm2));
00284           }
00285       }
00286     collisionModels.push_back (cm);
00287       }
00288 
00289       void RayTraceDetection::addCollisionPair (const std::pair <
00290                           core::CollisionModel *,
00291                           core::CollisionModel * >&cmPair)
00292       {
00293     typedef std::pair < std::pair < core::CollisionElementIterator,
00294       core::CollisionElementIterator >,
00295       std::pair < core::CollisionElementIterator,
00296       core::CollisionElementIterator > >TestPair;
00297 
00298 
00299     CubeModel *cm1 = dynamic_cast < CubeModel * >(cmPair.first);    
00300     CubeModel *cm2 = dynamic_cast < CubeModel * >(cmPair.second);   
00301     if (cm1 && cm2)
00302       {
00303         ctime_t t0, t1, t2;
00304         t0 = CTime::getRefTime ();
00305         findPairsVolume (cm1, cm2);
00306 
00307      
00308         t1 = CTime::getRefTime ();
00309         
00310         findPairsVolume (cm2, cm1);
00311         t2 = CTime::getRefTime ();  
00312       }
00313       }
00314 
00315       void RayTraceDetection::draw ()
00316       {
00317     if (!bDraw.getValue ())
00318       return;
00319 
00320     glDisable (GL_LIGHTING);
00321     glColor3f (1.0, 0.0, 1.0);
00322     glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
00323     glLineWidth (3);
00324     glPointSize (5);
00325 
00326     for (DetectionOutputMap::iterator it = outputsMap.begin ();
00327          it != outputsMap.end (); it++)
00328       {
00329         TDetectionOutputVector < TriangleOctreeModel,
00330           TriangleOctreeModel > *outputs =
00331           static_cast <
00332           sofa::core::componentmodel::collision::TDetectionOutputVector <
00333           TriangleOctreeModel, TriangleOctreeModel > *>(it->second);
00334         for (TDetectionOutputVector < TriangleOctreeModel,
00335          TriangleOctreeModel >::iterator it2 = (outputs)->begin ();
00336          it2 != outputs->end (); it2++)
00337           {
00338         glBegin (GL_LINES);
00339         glVertex3d (it2->point[0][0], it2->point[0][1],
00340                 it2->point[0][2]);
00341         glVertex3d (it2->point[1][0], it2->point[1][1],
00342                 it2->point[1][2]);
00343         glEnd ();
00344         std::cerr << it2->point[0] << " " << it2->
00345           point[0] << std::endl;
00346         it2->elem.first.draw ();
00347         it2->elem.second.draw ();
00348           }
00349       }
00350     glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
00351     glLineWidth (1);
00352     glPointSize (1);
00353       }
00354 
00355     }               // namespace collision
00356 
00357   }             // namespace component
00358 
00359 }               // namespace sofa

Generated on Sun Nov 23 02:35:10 2008 for Sofa by  doxygen 1.5.7.1