TriangleOctree.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/TriangleModel.h>
00026 #include <sofa/component/collision/TriangleOctree.h>
00027 #include <sofa/component/collision/CubeModel.h>
00028 #include <sofa/component/collision/RayTriangleIntersection.h>
00029 #include <sofa/component/collision/RayTriangleIntersection.h>
00030 
00031 #include <sofa/component/collision/Triangle.h>
00032 #include <sofa/core/CollisionElement.h>
00033 #include <sofa/core/ObjectFactory.h>
00034 #include <vector>
00035 #include <sofa/helper/system/thread/CTime.h>
00036 
00037 #include <cmath>
00038 #include <sofa/helper/system/gl.h>
00039 #include <sofa/helper/system/glut.h>
00040 
00041 
00042 namespace sofa
00043 {
00044 
00045   namespace component
00046   {
00047 
00048     namespace collision
00049     {
00050 
00051       using sofa::helper::system::thread::CTime;
00052       using sofa::helper::system::thread::ctime_t;
00053 
00054 TriangleOctree::~TriangleOctree (){
00055         for(int i=0;i<8;i++)
00056         {
00057             if(childVec[i]){
00058                 delete childVec[i];
00059                 childVec[i]=NULL;
00060                 }
00061         }
00062 }
00063       void TriangleOctree::draw ()
00064       {
00065 
00066     Vector3 center;
00067     if ( objects.size ())
00068       {
00069         center =
00070           (Vector3 (x, y, z) + Vector3 (size / 2, size / 2, size / 2));
00071         glPushMatrix ();
00072         glTranslatef (center[0], center[1], center[2]);
00073         glutWireCube (size);
00074         glPopMatrix ();
00075       }
00076     for (int i = 0; i < 8; i++)
00077       {
00078         if (childVec[i])
00079           childVec[i]->draw ();
00080       }
00081       }
00082 
00083       void TriangleOctree::insert (double _x, double _y, double _z,
00084                    double inc, int t)
00085       {
00086 
00087     
00088     if (inc >= size)
00089       {
00090         objects.push_back (t);
00091       }
00092     else
00093       {
00094 
00095         double size2 = size / 2;
00096         int dx = (_x >= (x + size2)) ? 1 : 0;
00097         int dy = (_y >= (y + size2)) ? 1 : 0;
00098         int dz = (_z >= (z + size2)) ? 1 : 0;
00099 
00100         int i = dx * 4 + dy * 2 + dz;
00101         if (!childVec[i])
00102           {
00103         is_leaf = false;
00104         childVec[i] =
00105           new TriangleOctree (tm, x + dx * size2, y + dy * size2,
00106                       z + dz * size2, size2);
00107           }
00108 
00109         childVec[i]->insert (_x, _y, _z, inc, t);
00110       }
00111       }
00112 
00113       inline
00114     unsigned int choose_next (double x, double y, double z,
00115                   unsigned int a, unsigned int b,
00116                   unsigned int c)
00117       {
00118     if (x < y)
00119       {
00120         if (x < z)
00121           return a;
00122         else
00123           return c;
00124       }
00125     else
00126       {
00127         if (y < z)
00128           return b;
00129         else
00130           return c;
00131       }
00132       }
00133 
00134       int TriangleOctree::nearestTriangle (int minIndex,
00135                        const Vector3 & origin,
00136                        const Vector3 & direction, traceResult &result)
00137       {
00138     static RayTriangleIntersection intersectionSolver;
00139     Vector3 P;
00140     Triangle t1 (tm, minIndex);
00141     double minDist;
00142     double t, u, v;
00143     if (intersectionSolver.NewComputation (&t1, origin, direction, t, u, v))
00144       {
00145     result.u=u;
00146     result.v=v;
00147     result.t=minDist = t;
00148 
00149       }
00150     else
00151       {
00152         minDist = 10e8;
00153     
00154         minIndex = -1;
00155       }
00156     for (unsigned int i = 0; i < objects.size (); i++)
00157       {
00158 
00159         Triangle t2 (tm, objects[i]);
00160     if (!intersectionSolver.
00161         NewComputation (&t2, origin, direction, t, u, v))
00162           continue;
00163     
00164         if (t < minDist)
00165           {
00166 
00167         result.u=u;
00168         result.v=v;
00169         result.t=minDist = t;
00170     
00171         minIndex = objects[i];
00172 
00173           }
00174 
00175 
00176       }
00177 
00178 
00179     if (minIndex < 0) return minIndex;
00180 
00181     /*u=p2 v=p3 p1=1-u+v*/
00182     int pointR=-1;
00183     Triangle t3(tm,minIndex);
00184     if(result.u>0.99)
00185     pointR=t3.p2Index();
00186     
00187     if(result.v>0.99)
00188         pointR=t3.p3Index();
00189     if((result.u+result.v)<0.01)
00190         pointR=t3.p1Index();
00191     if(0&&pointR!=-1){
00192      
00193         double cosAng=dot(direction,t3.n());
00194 
00195     for(unsigned int i=0;i<tm->pTri[pointR].size();i++)
00196     {
00197     Triangle t2(tm,tm->pTri[pointR][i]);
00198     double cosAng2=dot(direction,t2.n());
00199     if(cosAng2>cosAng){
00200         cosAng=cosAng2;
00201         minIndex=tm->pTri[pointR][i];
00202     }
00203 
00204 
00205 }
00206 
00207 }
00208     
00209     return minIndex;
00210       }
00211 
00212       int TriangleOctree::trace (const Vector3 & origin,
00213                  const Vector3 & direction, double tx0,
00214                  double ty0, double tz0, double tx1,
00215                  double ty1, double tz1, unsigned int a,
00216                  unsigned int b,Vector3 &origin1,Vector3 &direction1,traceResult &result)
00217       {
00218 
00219 
00220     if (tx1 < 0.0 || ty1 < 0.0 || tz1 < 0.0)
00221       return -1;
00222 
00223 
00224     if (is_leaf)
00225       {
00226         if (objects.size ())
00227           {
00228 
00229         return nearestTriangle (objects[0], origin1, direction1,result);
00230 
00231           }
00232         else
00233           {
00234         return -1;
00235           }
00236       }
00237 
00238     const double &x0 = x;
00239     const double &y0 = y;
00240     const double &z0 = z;
00241     const double &x1 = x + size;
00242     const double &y1 = y + size;
00243     const double &z1 = z + size;
00244     const double INF = 1e9;
00245 
00246     double txm=0, tym=0, tzm=0;
00247 
00248     switch (b)
00249       {
00250       case 0:
00251         txm = 0.5 * (tx0 + tx1);
00252         tym = 0.5 * (ty0 + ty1);
00253         tzm = 0.5 * (tz0 + tz1);
00254         break;
00255       case 1:
00256         txm = 0.5 * (tx0 + tx1);
00257         tym = 0.5 * (ty0 + ty1);
00258         tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00259         break;
00260       case 2:
00261         txm = 0.5 * (tx0 + tx1);
00262         tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00263         tzm = 0.5 * (tz0 + tz1);
00264         break;
00265       case 3:
00266         txm = 0.5 * (tx0 + tx1);
00267         tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00268         tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00269         break;
00270       case 4:
00271         txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00272         tym = 0.5 * (ty0 + ty1);
00273         tzm = 0.5 * (tz0 + tz1);
00274         break;
00275       case 5:
00276         txm = (origin[0] < (0.5 * (x0 + x1)) )? +INF : -INF;
00277         tym = 0.5 * (ty0 + ty1);
00278         tzm = (origin[2] < (0.5 * (z0 + z1) ))? +INF : -INF;
00279         break;
00280       case 6:
00281         txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00282         tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00283         tzm = 0.5 * (tz0 + tz1);
00284         break;
00285       case 7:
00286         txm = origin[0] < 0.5 * (x0 + x1) ? +INF : -INF;
00287         tym = origin[1] < 0.5 * (y0 + y1) ? +INF : -INF;
00288         tzm = origin[2] < 0.5 * (z0 + z1) ? +INF : -INF;
00289         break;
00290       default:
00291         assert (!"Internal failure.");
00292       }
00293     unsigned int current_octant = 0;
00294 
00295     if (tx0 > ty0)
00296       {
00297         if (tx0 > tz0)
00298           {
00299 //      max(tx0, ty0, tz0) is tx0. Entry plane is YZ.
00300         if (tym < tx0)
00301           current_octant |= 2;
00302         if (tzm < tx0)
00303           current_octant |= 1;
00304           }
00305         else
00306           {
00307     //  max(tx0, ty0, tz0) is tz0. Entry plane is XY.
00308         if (txm < tz0)
00309           current_octant |= 4;
00310         if (tym < tz0)
00311           current_octant |= 2;
00312           }
00313       }
00314     else
00315       {
00316         if (ty0 > tz0)
00317           {
00318         //max(tx0, ty0, tz0) is ty0. Entry plane is XZ.
00319         if (txm < ty0)
00320           current_octant |= 4;
00321         if (tzm < ty0)
00322           current_octant |= 1;
00323           }
00324         else
00325           {
00326     //  max(tx0, ty0, tz0) is tz0. Entry plane is XY.
00327         if (txm < tz0)
00328           current_octant |= 4;
00329         if (tym < tz0)
00330           current_octant |= 2;
00331           }
00332       }
00333 
00334 //  This special state indicates algorithm termination.
00335     const unsigned int END = 8;
00336 
00337     while (true)
00338       {
00339         int idxMin=-1;
00340         switch (current_octant)
00341           {
00342           case 0:
00343         if (childVec[a])
00344           {
00345             idxMin =
00346               childVec[a]->trace (origin, direction, tx0, ty0, tz0,
00347                       txm, tym, tzm, a, b,origin1,direction1,result);
00348             if (idxMin != -1)
00349               return nearestTriangle (idxMin, origin1, direction1,result);
00350           }
00351         current_octant = choose_next (txm, tym, tzm, 4, 2, 1);
00352         break;
00353 
00354 
00355 
00356 
00357           case 1:
00358         if (childVec[1 ^ a])
00359           {
00360             idxMin =
00361               childVec[1 ^ a]->trace (origin, direction, tx0, ty0,
00362                           tzm, txm, tym, tz1, a, b,origin1,direction1,result);
00363             if (idxMin != -1)
00364               return nearestTriangle (idxMin, origin1, direction1,result);
00365           }
00366         current_octant = choose_next (txm, tym, tz1, 5, 3, END);
00367         break;
00368 
00369 
00370 
00371           case 2:
00372         if (childVec[2 ^ a])
00373           {
00374             idxMin =
00375               childVec[2 ^ a]->trace (origin, direction, tx0, tym,
00376                           tz0, txm, ty1, tzm, a, b,origin1,direction1,result);
00377             if (idxMin != -1)
00378               return nearestTriangle (idxMin, origin1, direction1,result);
00379           }
00380         current_octant = choose_next (txm, ty1, tzm, 6, END, 3);
00381         break;
00382           case 3:
00383         if (childVec[3 ^ a])
00384           {
00385             idxMin =
00386               childVec[3 ^ a]->trace (origin, direction, tx0, tym,
00387                           tzm, txm, ty1, tz1, a, b,origin1,direction1,result);
00388             if (idxMin != -1)
00389               return nearestTriangle (idxMin, origin1, direction1,result);
00390           }
00391         current_octant = choose_next (txm, ty1, tz1, 7, END, END);
00392         break;
00393           case 4:
00394         if (childVec[4 ^ a])
00395           {
00396             idxMin =
00397               childVec[4 ^ a]->trace (origin, direction, txm, ty0,
00398                           tz0, tx1, tym, tzm, a, b,origin1,direction1,result);
00399             if (idxMin != -1)
00400               return nearestTriangle (idxMin, origin1, direction1,result);
00401           }
00402         current_octant = choose_next (tx1, tym, tzm, END, 6, 5);
00403         break;
00404           case 5:
00405         if (childVec[5 ^ a])
00406           {
00407             idxMin =
00408               childVec[5 ^ a]->trace (origin, direction, txm, ty0,
00409                           tzm, tx1, tym, tz1, a, b,origin1,direction1,result);
00410             if (idxMin != -1)
00411               return nearestTriangle (idxMin, origin1, direction1,result);
00412           }
00413         current_octant = choose_next (tx1, tym, tz1, END, 7, END);
00414         break;
00415           case 6:
00416         if (childVec[6 ^ a])
00417           {
00418             idxMin =
00419               childVec[6 ^ a]->trace (origin, direction, txm, tym,
00420                           tz0, tx1, ty1, tzm, a, b,origin1,direction1,result);
00421             if (idxMin != -1)
00422               return nearestTriangle (idxMin, origin1, direction1,result);
00423           }
00424         current_octant = choose_next (tx1, ty1, tzm, END, END, 7);
00425         break;
00426           case 7:
00427         if (childVec[7 ^ a])
00428           {
00429             idxMin =
00430               childVec[7 ^ a]->trace (origin, direction, txm, tym,
00431                           tzm, tx1, ty1, tz1, a, b,origin1,direction1,result);
00432             if (idxMin != -1)
00433               return nearestTriangle (idxMin, origin1, direction1,result);
00434           }
00435           case END:
00436         if(idxMin==-1&&objects.size())
00437           return nearestTriangle (objects[0], origin1, direction1,result);
00438          return idxMin;    
00439           }
00440       }
00441 
00442 
00443       }
00444 
00445 
00446       int TriangleOctree::trace (Vector3 origin, Vector3 direction,traceResult &result)
00447       {
00448     unsigned int a = 0;
00449     unsigned int b = 0;
00450     //const double EPSILON = 1e-8;
00451     const double EPSILON = 0;
00452     Vector3 origin1=origin;
00453     Vector3 direction1=direction;
00454 
00455     if (direction[0] == 0.0)
00456       {
00457     direction[0]=EPSILON;
00458         b |= 4;
00459       }
00460     else if (direction[0] < 0.0)
00461       {
00462 
00463         origin[0] = -origin[0];
00464         direction[0] = -direction[0];
00465         a |= 4;
00466       }
00467 
00468     if (direction[1] == 0.0)
00469       {
00470     direction[1]=EPSILON;
00471         b |= 2;
00472       }
00473     else if (direction[1] < 0.0)
00474       {
00475         origin[1] = -origin[1];
00476         direction[1] = -direction[1];
00477         a |= 2;
00478       }
00479 
00480     if (direction[2] == 0.0)
00481       {
00482     direction[2]=EPSILON;  
00483       b |= 1;
00484       }
00485     else if (direction[2] < 0.0)
00486       {
00487         origin[2] = -origin[2];
00488         direction[2] = -direction[2];
00489         a |= 1;
00490       }
00491     double tx0 = (-CUBE_SIZE - origin[0]) / direction[0];
00492     double tx1 = (CUBE_SIZE - origin[0]) / direction[0];
00493     double ty0 = (-CUBE_SIZE - origin[1]) / direction[1];
00494     double ty1 = (CUBE_SIZE - origin[1]) / direction[1];
00495     double tz0 = (-CUBE_SIZE - origin[2]) / direction[2];
00496     double tz1 = (CUBE_SIZE - origin[2]) / direction[2];
00497     if (bb_max3 (tx0, ty0, tz0) < bb_min3 (tx1, ty1, tz1))
00498       return trace (origin, direction, tx0, ty0, tz0, tx1, ty1, tz1, a, b,origin1,direction1,result);
00499     return -1;
00500 
00501       }
00502 
00503      
00504      
00505 
00506 
00507     }               // namespace collision
00508 
00509   }             // namespace component
00510 
00511 }               // namespace sofa

Generated on Sun Nov 23 02:37:12 2008 for Sofa by  doxygen 1.5.7.1