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 #include <sofa/helper/system/config.h>
00026 #include <sofa/component/collision/NewProximityIntersection.inl>
00027 #include <sofa/core/ObjectFactory.h>
00028 #include <sofa/component/collision/proximity.h>
00029 #include <sofa/defaulttype/Mat.h>
00030 #include <sofa/defaulttype/Vec.h>
00031 #include <sofa/core/componentmodel/collision/Intersection.inl>
00032 #include <iostream>
00033 #include <algorithm>
00034
00035
00036 namespace sofa
00037 {
00038
00039 namespace component
00040 {
00041
00042 namespace collision
00043 {
00044
00045 using namespace sofa::defaulttype;
00046 using namespace sofa::core::componentmodel::collision;
00047 using namespace helper;
00048
00049 SOFA_DECL_CLASS(NewProximityIntersection)
00050
00051 int NewProximityIntersectionClass = core::RegisterObject("Optimized Proximity Intersection based on Triangle-Triangle tests, ignoring Edge-Edge cases")
00052 .add< NewProximityIntersection >()
00053 ;
00054
00055 NewProximityIntersection::NewProximityIntersection()
00056 : alarmDistance(initData(&alarmDistance, 1.0, "alarmDistance","Proximity detection distance"))
00057 , contactDistance(initData(&contactDistance, 0.5, "contactDistance","Distance below which a contact is created"))
00058 {
00059 }
00060
00061 void NewProximityIntersection::init()
00062 {
00063 intersectors.add<CubeModel, CubeModel, NewProximityIntersection>(this);
00064 intersectors.add<PointModel, PointModel, NewProximityIntersection>(this);
00065 intersectors.add<SphereModel, PointModel, NewProximityIntersection>(this);
00066 intersectors.add<SphereModel, SphereModel, NewProximityIntersection>(this);
00067 intersectors.add<LineModel, PointModel, NewProximityIntersection>(this);
00068 intersectors.add<LineModel, SphereModel, NewProximityIntersection>(this);
00069 intersectors.add<LineModel, LineModel, NewProximityIntersection>(this);
00070 intersectors.add<TriangleModel, PointModel, NewProximityIntersection>(this);
00071 intersectors.add<TriangleModel, SphereModel, NewProximityIntersection>(this);
00072 intersectors.add<TriangleModel, LineModel, NewProximityIntersection>(this);
00073 intersectors.add<TriangleModel, TriangleModel, NewProximityIntersection>(this);
00074
00075 intersectors.ignore<RayModel, PointModel>();
00076 intersectors.ignore<RayModel, LineModel>();
00077 intersectors.add<RayModel, TriangleModel, NewProximityIntersection>(this);
00078 }
00079
00080 bool NewProximityIntersection::testIntersection(Cube &cube1, Cube &cube2)
00081 {
00082 const Vector3& minVect1 = cube1.minVect();
00083 const Vector3& minVect2 = cube2.minVect();
00084 const Vector3& maxVect1 = cube1.maxVect();
00085 const Vector3& maxVect2 = cube2.maxVect();
00086 const double alarmDist = getAlarmDistance() + cube1.getProximity() + cube2.getProximity();
00087
00088 for (int i=0;i<3;i++)
00089 {
00090 if ( minVect1[i] > maxVect2[i] + alarmDist || minVect2[i]> maxVect1[i] + alarmDist )
00091 return false;
00092 }
00093
00094 return true;
00095 }
00096
00097 int NewProximityIntersection::computeIntersection(Cube&, Cube&, OutputVector* )
00098 {
00099 return 0;
00100 }
00101
00102 bool NewProximityIntersection::testIntersection(Point& e1, Point& e2)
00103 {
00104 OutputVector contacts;
00105 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00106 int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.p(), e2.p(), &contacts, -1);
00107 return n>0;
00108 }
00109
00110 int NewProximityIntersection::computeIntersection(Point& e1, Point& e2, OutputVector* contacts)
00111 {
00112 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00113 int n = doIntersectionPointPoint(alarmDist*alarmDist, e1.p(), e2.p(), contacts, (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex());
00114 if (n>0)
00115 {
00116 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00117 for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00118 {
00119 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00120 detection->value -= contactDist;
00121 }
00122 }
00123 return n;
00124 }
00125
00126 bool NewProximityIntersection::testIntersection(Line&, Point&)
00127 {
00128 std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Line,Point).\n";
00129 return true;
00130 }
00131
00132 int NewProximityIntersection::computeIntersection(Line& e1, Point& e2, OutputVector* contacts)
00133 {
00134 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00135 int n = doIntersectionLinePoint(alarmDist*alarmDist, e1.p1(),e1.p2(), e2.p(), contacts, e2.getIndex());
00136 if (n>0)
00137 {
00138 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00139 for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00140 {
00141 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00142 detection->value -= contactDist;
00143 }
00144 }
00145 return n;
00146 }
00147
00148 bool NewProximityIntersection::testIntersection(Line&, Line&)
00149 {
00150 std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Line,Line).\n";
00151 return true;
00152 }
00153
00154 int NewProximityIntersection::computeIntersection(Line& e1, Line& e2, OutputVector* contacts)
00155 {
00156 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00157 const double dist2 = alarmDist*alarmDist;
00158 const int id = (e1.getCollisionModel()->getSize() > e2.getCollisionModel()->getSize()) ? e1.getIndex() : e2.getIndex();
00159 int n = doIntersectionLineLine(dist2, e1.p1(),e1.p2(), e2.p1(),e2.p2(), contacts, id);
00160 if (n>0)
00161 {
00162 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00163 for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00164 {
00165 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00166 detection->value -= contactDist;
00167 }
00168 }
00169 return n;
00170 }
00171
00172 bool NewProximityIntersection::testIntersection(Triangle&, Point&)
00173 {
00174 std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle,Point).\n";
00175 return true;
00176 }
00177
00178 int NewProximityIntersection::computeIntersection(Triangle& e1, Point& e2, OutputVector* contacts)
00179 {
00180 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00181 const double dist2 = alarmDist*alarmDist;
00182 int n = doIntersectionTrianglePoint(dist2, e1.flags(),e1.p1(),e1.p2(),e1.p3(),e1.n(), e2.p(), contacts, e2.getIndex());
00183 if (n>0)
00184 {
00185 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00186 for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00187 {
00188 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00189 detection->value -= contactDist;
00190 }
00191 }
00192 return n;
00193 }
00194
00195 bool NewProximityIntersection::testIntersection(Triangle&, Line&)
00196 {
00197 std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle& e1, Line& e2).\n";
00198 return true;
00199 }
00200
00201 int NewProximityIntersection::computeIntersection(Triangle& e1, Line& e2, OutputVector* contacts)
00202 {
00203 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00204 const double dist2 = alarmDist*alarmDist;
00205 const Vector3& p1 = e1.p1();
00206 const Vector3& p2 = e1.p2();
00207 const Vector3& p3 = e1.p3();
00208 const Vector3& pn = e1.n();
00209 const Vector3& q1 = e2.p1();
00210 const Vector3& q2 = e2.p2();
00211
00212 const int f1 = e1.flags();
00213
00214 int n = 0;
00215
00216 if (f1&TriangleModel::FLAG_P1)
00217 {
00218 n += doIntersectionLinePoint(dist2, q1,q2, p1, contacts, e2.getIndex(), true);
00219 }
00220 if (f1&TriangleModel::FLAG_P2)
00221 {
00222 n += doIntersectionLinePoint(dist2, q1,q2, p2, contacts, e2.getIndex(), true);
00223 }
00224 if (f1&TriangleModel::FLAG_P3)
00225 {
00226 n += doIntersectionLinePoint(dist2, q1,q2, p3, contacts, e2.getIndex(), true);
00227 }
00228
00229 n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q1, contacts, e2.getIndex(), false);
00230 n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q2, contacts, e2.getIndex(), false);
00231
00232 if (n>0)
00233 {
00234 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00235 for (OutputVector::iterator detection = contacts->end()-n; detection != contacts->end(); ++detection)
00236 {
00237 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00238 detection->value -= contactDist;
00239 }
00240 }
00241 return n;
00242 }
00243
00244
00245 bool NewProximityIntersection::testIntersection(Triangle&, Triangle&)
00246 {
00247 std::cerr << "Unnecessary call to NewProximityIntersection::testIntersection(Triangle& e1, Triangle& e2).\n";
00248 return true;
00249 }
00250
00251 int NewProximityIntersection::computeIntersection(Triangle& e1, Triangle& e2, OutputVector* contacts)
00252 {
00253 if (e1.getIndex() >= e1.getCollisionModel()->getSize())
00254 {
00255 std::cerr << "NewProximityIntersection::computeIntersection(Triangle, Triangle): ERROR invalid e1 index "<<e1.getIndex()<<" on CM "<<e1.getCollisionModel()->getName()<<" of size "<<e1.getCollisionModel()->getSize()<<std::endl;
00256 return 0;
00257 }
00258 if (e2.getIndex() >= e2.getCollisionModel()->getSize())
00259 {
00260 std::cerr << "NewProximityIntersection::computeIntersection(Triangle, Triangle): ERROR invalid e2 index "<<e2.getIndex()<<" on CM "<<e2.getCollisionModel()->getName()<<" of size "<<e2.getCollisionModel()->getSize()<<std::endl;
00261 return 0;
00262 }
00263 const double alarmDist = getAlarmDistance() + e1.getProximity() + e2.getProximity();
00264 const double dist2 = alarmDist*alarmDist;
00265 const Vector3& p1 = e1.p1();
00266 const Vector3& p2 = e1.p2();
00267 const Vector3& p3 = e1.p3();
00268 const Vector3& pn = e1.n();
00269 const Vector3& q1 = e2.p1();
00270 const Vector3& q2 = e2.p2();
00271 const Vector3& q3 = e2.p3();
00272 const Vector3& qn = e2.n();
00273
00274 const int f1 = e1.flags();
00275 const int f2 = e2.flags();
00276
00277 const int id1 = e1.getIndex()*3;
00278 const int id2 = e1.getCollisionModel()->getSize()*3 + e2.getIndex()*3;
00279
00280 int n = 0;
00281
00282 if (f1&TriangleModel::FLAG_P1)
00283 n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p1, contacts, id1+0, true);
00284 if (f1&TriangleModel::FLAG_P2)
00285 n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p2, contacts, id1+1, true);
00286 if (f1&TriangleModel::FLAG_P3)
00287 n += doIntersectionTrianglePoint(dist2, f2,q1,q2,q3,qn, p3, contacts, id1+2, true);
00288
00289 if (f2&TriangleModel::FLAG_P1)
00290 n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q1, contacts, id2+0, false);
00291 if (f2&TriangleModel::FLAG_P2)
00292 n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q2, contacts, id2+1, false);
00293 if (f2&TriangleModel::FLAG_P3)
00294 n += doIntersectionTrianglePoint(dist2, f1,p1,p2,p3,pn, q3, contacts, id2+2, false);
00295
00296 if (n>0)
00297 {
00298 const double contactDist = getContactDistance() + e1.getProximity() + e2.getProximity();
00299
00300 for (int i=0;i<n;++i)
00301 {
00302
00303
00304 (*contacts)[contacts->size()-n+i].elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(e1, e2);
00305 (*contacts)[contacts->size()-n+i].value -= contactDist;
00306
00307 }
00308 }
00309 return n;
00310 }
00311
00312
00313 bool NewProximityIntersection::testIntersection(Ray &t1,Triangle &t2)
00314 {
00315 Vector3 P,Q,PQ;
00316 static DistanceSegTri proximitySolver;
00317 const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00318
00319 if (fabs(t2.n() * t1.direction()) < 0.000001)
00320 return false;
00321
00322 Vector3 A = t1.origin();
00323 Vector3 B = A + t1.direction() * t1.l();
00324
00325 proximitySolver.NewComputation( &t2, A, B,P,Q);
00326 PQ = Q-P;
00327
00328 if (PQ.norm2() < alarmDist*alarmDist)
00329 {
00330
00331 return true;
00332 }
00333 else
00334 return false;
00335 }
00336
00337 int NewProximityIntersection::computeIntersection(Ray &t1, Triangle &t2, OutputVector* contacts)
00338 {
00339 const double alarmDist = getAlarmDistance() + t1.getProximity() + t2.getProximity();
00340
00341 if (fabs(t2.n() * t1.direction()) < 0.000001)
00342 return false;
00343
00344 Vector3 A = t1.origin();
00345 Vector3 B = A + t1.direction() * t1.l();
00346
00347 Vector3 P,Q,PQ;
00348 static DistanceSegTri proximitySolver;
00349
00350 proximitySolver.NewComputation( &t2, A,B,P,Q);
00351 PQ = Q-P;
00352
00353 if (PQ.norm2() >= alarmDist*alarmDist)
00354 return 0;
00355
00356 const double contactDist = alarmDist;
00357 contacts->resize(contacts->size()+1);
00358 DetectionOutput *detection = &*(contacts->end()-1);
00359
00360 detection->elem = std::pair<core::CollisionElementIterator, core::CollisionElementIterator>(t1, t2);
00361 detection->point[1]=P;
00362 detection->point[0]=Q;
00363 #ifdef DETECTIONOUTPUT_FREEMOTION
00364 detection->freePoint[1] = P;
00365 detection->freePoint[0] = Q;
00366 #endif
00367 detection->normal=-t2.n();
00368 detection->value = PQ.norm();
00369 detection->value -= contactDist;
00370 return 1;
00371 }
00372
00373 }
00374
00375 }
00376
00377 }
00378