00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
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
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
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
00097 if (!tm1->octreeRoot)
00098 {
00099
00100 tm1->buildOctree ();
00101 }
00102
00103 if (!tm2->octreeRoot)
00104 {
00105
00106 tm2->buildOctree ();
00107
00108 }
00109
00110
00111
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
00144 Triangle tri1 (tm1, j);
00145
00146
00147
00148 double cosAngle;
00149
00150 double cosAngle2;
00151
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
00159
00160
00161
00162
00163
00164
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
00195 TriangleOctree::traceResult res, res2;
00196
00197 resTriangle =
00198 tm2->octreeRoot->
00199 trace (point ,
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
00208
00209
00210
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
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 }
00356
00357 }
00358
00359 }