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/helper/FnDispatcher.inl>
00027 #include <sofa/component/collision/DiscreteIntersection.inl>
00028 #include <sofa/core/ObjectFactory.h>
00029 #include <sofa/core/componentmodel/collision/Intersection.inl>
00030
00031
00032 #include <sofa/component/collision/proximity.h>
00033 #include <iostream>
00034 #include <algorithm>
00035
00036
00037 namespace sofa
00038 {
00039
00040 namespace component
00041 {
00042
00043 namespace collision
00044 {
00045
00046 using namespace sofa::defaulttype;
00047 using namespace sofa::core::componentmodel::collision;
00048
00049 SOFA_DECL_CLASS(DiscreteIntersection)
00050
00051 int DiscreteIntersectionClass = core::RegisterObject("TODO-DiscreteIntersectionClass")
00052 .add< DiscreteIntersection >()
00053 ;
00054
00055
00056 DiscreteIntersection::DiscreteIntersection()
00057 {
00058 intersectors.add<CubeModel, CubeModel, DiscreteIntersection> (this);
00059 intersectors.add<SphereModel, SphereModel, DiscreteIntersection> (this);
00060 intersectors.add<SphereTreeModel, SphereTreeModel, DiscreteIntersection> (this);
00061 intersectors.add<SphereTreeModel, CubeModel, DiscreteIntersection> (this);
00062 intersectors.add<SphereTreeModel, TriangleModel, DiscreteIntersection> (this);
00063
00064
00065 intersectors.add<TriangleModel, LineModel, DiscreteIntersection> (this);
00066
00067 intersectors.add<TetrahedronModel, PointModel, DiscreteIntersection> (this);
00068 intersectors.add<RigidDistanceGridCollisionModel, PointModel, DiscreteIntersection> (this);
00069 intersectors.add<RigidDistanceGridCollisionModel, SphereModel, DiscreteIntersection> (this);
00070 intersectors.add<RigidDistanceGridCollisionModel, TriangleModel, DiscreteIntersection> (this);
00071 intersectors.add<RigidDistanceGridCollisionModel, RigidDistanceGridCollisionModel, DiscreteIntersection> (this);
00072 intersectors.add<FFDDistanceGridCollisionModel, PointModel, DiscreteIntersection> (this);
00073 intersectors.add<FFDDistanceGridCollisionModel, SphereModel, DiscreteIntersection> (this);
00074 intersectors.add<FFDDistanceGridCollisionModel, TriangleModel, DiscreteIntersection> (this);
00075 intersectors.add<FFDDistanceGridCollisionModel, RigidDistanceGridCollisionModel, DiscreteIntersection> (this);
00076 intersectors.add<FFDDistanceGridCollisionModel, FFDDistanceGridCollisionModel, DiscreteIntersection> (this);
00077
00078 intersectors.add<RayModel, SphereModel, DiscreteIntersection> (this);
00079 intersectors.add<RayModel, SphereTreeModel, DiscreteIntersection> (this);
00080 intersectors.ignore<RayModel, PointModel>();
00081 intersectors.ignore<RayModel, LineModel>();
00082 intersectors.add<RayModel, TriangleModel, DiscreteIntersection> (this);
00083 intersectors.add<RayModel, TetrahedronModel, DiscreteIntersection> (this);
00084 intersectors.add<RayModel, RigidDistanceGridCollisionModel, DiscreteIntersection> (this);
00085 intersectors.add<RayModel, FFDDistanceGridCollisionModel, DiscreteIntersection> (this);
00086 }
00087
00089 ElementIntersector* DiscreteIntersection::findIntersector(core::CollisionModel* object1, core::CollisionModel* object2, bool& swapModels)
00090 {
00091 return intersectors.get(object1, object2, swapModels);
00092 }
00093
00094 bool DiscreteIntersection::testIntersection(Cube& cube1, Cube& cube2)
00095 {
00096 const Vector3& minVect1 = cube1.minVect();
00097 const Vector3& minVect2 = cube2.minVect();
00098 const Vector3& maxVect1 = cube1.maxVect();
00099 const Vector3& maxVect2 = cube2.maxVect();
00100
00101 for (int i=0;i<3;i++)
00102 {
00103 if (minVect1[i] > maxVect2[i] || minVect2[i] > maxVect1[i])
00104 return false;
00105 }
00106
00107
00108
00109 return true;
00110 }
00111
00112
00113
00114
00115
00116
00117
00118 int DiscreteIntersection::computeIntersection(Cube&, Cube&, OutputVector*)
00119 {
00120 return 0;
00121 }
00122
00123
00124
00125
00126
00127
00128
00129 bool DiscreteIntersection::testIntersection(Triangle&, Line&)
00130 {
00131 return true;
00132 }
00133
00134 int DiscreteIntersection::computeIntersection(Triangle& e1, Line& e2, OutputVector* contacts)
00135 {
00136 Vector3 A = e1.p1();
00137 Vector3 AB = e1.p2()-A;
00138 Vector3 AC = e1.p3()-A;
00139 Vector3 P = e2.p1();
00140 Vector3 PQ = e2.p2()-P;
00141 Matrix3 M, Minv;
00142 Vector3 right;
00143 for (int i=0;i<3;i++)
00144 {
00145 M[i][0] = AB[i];
00146 M[i][1] = AC[i];
00147 M[i][2] = -PQ[i];
00148 right[i] = P[i]-A[i];
00149 }
00150
00151 if (!Minv.invert(M))
00152 return 0;
00153 Vector3 baryCoords = Minv * right;
00154 if (baryCoords[0] < 0 || baryCoords[1] < 0 || baryCoords[0]+baryCoords[1] > 1)
00155 return 0;
00156 if (baryCoords[2] < 0 || baryCoords[2] > 1)
00157 return 0;
00158
00159 Vector3 X = P+PQ*baryCoords[2];
00160
00161 contacts->resize(contacts->size()+1);
00162 DetectionOutput *detection = &*(contacts->end()-1);
00163 detection->point[0] = X;
00164 detection->point[1] = X;
00165 detection->normal = e1.n();
00166 detection->value = 0;
00167 detection->elem.first = e1;
00168 detection->elem.second = e2;
00169 detection->id = e2.getIndex();
00170 return 1;
00171 }
00172
00173 bool DiscreteIntersection::testIntersection(Ray&, Triangle&)
00174 {
00175 return true;
00176 }
00177
00178 int DiscreteIntersection::computeIntersection(Ray& e1, Triangle& e2, OutputVector* contacts)
00179 {
00180 Vector3 A = e2.p1();
00181 Vector3 AB = e2.p2()-A;
00182 Vector3 AC = e2.p3()-A;
00183 Vector3 P = e1.origin();
00184 Vector3 PQ = e1.direction();
00185 Matrix3 M, Minv;
00186 Vector3 right;
00187 for (int i=0;i<3;i++)
00188 {
00189 M[i][0] = AB[i];
00190 M[i][1] = AC[i];
00191 M[i][2] = -PQ[i];
00192 right[i] = P[i]-A[i];
00193 }
00194 if (!Minv.invert(M))
00195 return 0;
00196 Vector3 baryCoords = Minv * right;
00197 if (baryCoords[0] < 0 || baryCoords[1] < 0 || baryCoords[0]+baryCoords[1] > 1)
00198 return 0;
00199 if (baryCoords[2] < 0 || baryCoords[2] > e1.l())
00200 return 0;
00201
00202 Vector3 X = P+PQ*baryCoords[2];
00203
00204 contacts->resize(contacts->size()+1);
00205 DetectionOutput *detection = &*(contacts->end()-1);
00206 detection->point[0] = X;
00207 detection->point[1] = X;
00208 detection->normal = -e2.n();
00209 detection->value = 0;
00210 detection->elem.first = e1;
00211 detection->elem.second = e2;
00212 detection->id = e1.getIndex();
00213 return 1;
00214 }
00215
00216 bool DiscreteIntersection::testIntersection(Ray&, Tetrahedron&)
00217 {
00218 return true;
00219 }
00220
00221 int DiscreteIntersection::computeIntersection(Ray& e1, Tetrahedron& e2, OutputVector* contacts)
00222 {
00223 Vector3 P = e1.origin();
00224 Vector3 PQ = e1.direction();
00225 Vector3 b0 = e2.getBary(P);
00226 Vector3 bdir = e2.getDBary(PQ);
00227
00228 double l0 = 0;
00229 double l1 = e1.l();
00230 for (int c=0;c<3;++c)
00231 {
00232 if (b0[c] < 0 && bdir[c] < 0) return 0;
00233
00234 if (bdir[c] < -1.0e-10)
00235 {
00236 double l = -b0[c]/bdir[c];
00237 if (l < l1) l1 = l;
00238 }
00239 else if (bdir[c] > 1.0e-10)
00240 {
00241 double l = -b0[c]/bdir[c];
00242 if (l > l0) l0 = l;
00243 }
00244 }
00245
00246 {
00247 double bd = bdir[0]+bdir[1]+bdir[2];
00248 if (bd > 1.0e-10)
00249 {
00250 double l = (1-(b0[0]+b0[1]+b0[2]))/bd;
00251 if (l < l1) l1 = l;
00252 }
00253 else if (bd < -1.0e-10)
00254 {
00255 double l = (1-(b0[0]+b0[1]+b0[2]))/bd;
00256 if (l > l0) l0 = l;
00257 }
00258 }
00259 if (l0 > l1) return 0;
00260 double l = l0;
00261 Vector3 X = P+PQ*l;
00262
00263
00264
00265
00266
00267 contacts->resize(contacts->size()+1);
00268 DetectionOutput *detection = &*(contacts->end()-1);
00269 detection->point[0] = X;
00270 detection->point[1] = X;
00271 PQ.normalize();
00272 detection->normal = PQ;
00273 detection->value = 0;
00274 detection->elem.first = e1;
00275 detection->elem.second = e2;
00276 detection->id = e1.getIndex();
00277 return 1;
00278 }
00279
00280 bool DiscreteIntersection::testIntersection(Tetrahedron&, Point&)
00281 {
00282 return true;
00283 }
00284
00285 int DiscreteIntersection::computeIntersection(Tetrahedron& e1, Point& e2, OutputVector* contacts)
00286 {
00287 Vector3 n = e2.n();
00288 if (n == Vector3()) return 0;
00289
00290 if (e1.getCollisionModel()->getMechanicalState() == e2.getCollisionModel()->getMechanicalState())
00291 {
00292 int i = e2.getIndex();
00293 if (i == e1.p1Index() || i == e1.p2Index() || i == e1.p3Index() || i == e1.p4Index())
00294 return 0;
00295 }
00296
00297 Vector3 P = e2.p();
00298 Vector3 b0 = e1.getBary(P);
00299 if (b0[0] < 0 || b0[1] < 0 || b0[2] < 0 || (b0[0]+b0[1]+b0[2]) > 1)
00300 return 1;
00301
00302
00303 Vector3 bdir = e1.getDBary(-n);
00304
00305 double l1 = 1.0e10;
00306 for (int c=0;c<3;++c)
00307 {
00308 if (bdir[c] < -1.0e-10)
00309 {
00310 double l = -b0[c]/bdir[c];
00311 if (l < l1) l1 = l;
00312 }
00313 }
00314
00315 {
00316 double bd = bdir[0]+bdir[1]+bdir[2];
00317 if (bd > 1.0e-10)
00318 {
00319 double l = (1-(b0[0]+b0[1]+b0[2]))/bd;
00320 if (l < l1) l1 = l;
00321 }
00322 }
00323 if (l1 >= 1.0e9) l1 = 0;
00324 double l = l1;
00325 Vector3 X = P-n*l;
00326
00327 contacts->resize(contacts->size()+1);
00328 DetectionOutput *detection = &*(contacts->end()-1);
00329 detection->point[0] = X;
00330 detection->point[1] = P;
00331 detection->normal = -n;
00332 detection->value = -l;
00333 detection->elem.first = e1;
00334 detection->elem.second = e2;
00335 detection->id = e2.getIndex();
00336 return 1;
00337 }
00338
00339 bool DiscreteIntersection::testIntersection(RigidDistanceGridCollisionElement&, RigidDistanceGridCollisionElement&)
00340 {
00341 return true;
00342 }
00343
00344
00345
00346 int DiscreteIntersection::computeIntersection(RigidDistanceGridCollisionElement& e1, RigidDistanceGridCollisionElement& e2, OutputVector* contacts)
00347 {
00348 int nc = 0;
00349 DistanceGrid* grid1 = e1.getGrid();
00350 DistanceGrid* grid2 = e2.getGrid();
00351 bool useXForm = e1.isTransformed() || e2.isTransformed();
00352 const Vector3& t1 = e1.getTranslation();
00353 const Matrix3& r1 = e1.getRotation();
00354 const Vector3& t2 = e2.getTranslation();
00355 const Matrix3& r2 = e2.getRotation();
00356
00357 const SReal margin = 0.001f;
00358
00359
00360 Vec3f translation;
00361 Mat3x3f rotation;
00362
00363 if (useXForm)
00364 {
00365
00366
00367
00368 translation = r2.multTranspose(t1-t2);
00369 rotation = r2.multTranspose ( r1 );
00370 }
00371 else rotation.identity();
00372
00373
00374
00375
00376
00377
00378 enum { FACE_NONE=-1,FACE_XNEG=0,FACE_XPOS,FACE_YNEG,FACE_YPOS,FACE_ZNEG,FACE_ZPOS };
00379 int face_e1 = FACE_NONE;
00380 int face_e2 = FACE_NONE;
00381
00382 if (grid2->isCube() && grid1->isCube())
00383 {
00384 const SReal cubeDim1 = grid1->getCubeDim();
00385 const SReal cubeDim2 = grid2->getCubeDim();
00386
00387
00388 SReal dist = (SReal)((cubeDim1 + cubeDim2) * 0.1);
00389
00390 for (int f2 = 0; f2 < 3; f2++)
00391 {
00392 for (int f1 = 0; f1 < 3; f1++)
00393 {
00394 if (rotation[f2][f1] < -0.99 || rotation[f2][f1] > 0.99)
00395 {
00396
00397
00398 SReal d = rabs(rabs(translation[f2])-(cubeDim1+cubeDim2));
00399
00400
00401 if (rabs(r2[f2][2]) > 0.99 && d < (cubeDim1 + cubeDim2) * 0.1) d = 0;
00402 if (d < dist)
00403 {
00404 dist = d;
00405 if (translation[f2] > 0)
00406 {
00407 face_e2 = 2*f2+1;
00408 if (rotation[f2][f1] > 0)
00409 {
00410 face_e1 = 2*f1;
00411 }
00412 else
00413 {
00414 face_e1 = 2*f1+1;
00415 }
00416 }
00417 else
00418 {
00419 face_e2 = 2*f2;
00420 if (rotation[f2][f1] > 0)
00421 {
00422 face_e1 = 2*f1+1;
00423 }
00424 else
00425 {
00426 face_e1 = 2*f1;
00427 }
00428 }
00429 }
00430 }
00431 }
00432 }
00433 }
00434
00435
00436 const DistanceGrid::VecCoord& x1 = grid1->meshPts;
00437 if (!x1.empty() && e1.getCollisionModel()->usePoints.getValue())
00438 {
00439 if (grid2->isCube() && grid1->isCube())
00440 {
00441 const SReal cubeDim2 = grid2->getCubeDim();
00442 const SReal cubeDim2Margin = cubeDim2+margin;
00443
00444 if (face_e2 != FACE_NONE)
00445 {
00446 DistanceGrid::Coord normal;
00447 normal[face_e2/2] = (face_e2&1)?1.0f:-1.0f;
00448 Vector3 gnormal = r2 * -normal;
00449
00450 if (gnormal[0] < -0.99f) gnormal = Vector3(-1.0f, 0.0f, 0.0f);
00451 else if (gnormal[0] > 0.99f) gnormal = Vector3( 1.0f, 0.0f, 0.0f);
00452 if (gnormal[1] < -0.99f) gnormal = Vector3( 0.0f,-1.0f, 0.0f);
00453 else if (gnormal[1] > 0.99f) gnormal = Vector3( 0.0f, 1.0f, 0.0f);
00454 if (gnormal[2] < -0.99f) gnormal = Vector3( 0.0f, 0.0f, -1.0f);
00455 else if (gnormal[2] > 0.99f) gnormal = Vector3( 0.0f, 0.0f, 1.0f);
00456 for (unsigned int i=0; i<x1.size(); i++)
00457 {
00458 DistanceGrid::Coord p1 = x1[i];
00459 DistanceGrid::Coord p2 = translation + rotation*p1;
00460 if (p2[0] < -cubeDim2Margin || p2[0] > cubeDim2Margin ||
00461 p2[1] < -cubeDim2Margin || p2[1] > cubeDim2Margin ||
00462 p2[2] < -cubeDim2Margin || p2[2] > cubeDim2Margin)
00463 continue;
00464 double d = p2*normal - cubeDim2;
00465
00466 p2 -= normal * d;
00467
00468 contacts->resize(contacts->size()+1);
00469 DetectionOutput *detection = &*(contacts->end()-1);
00470
00471 detection->point[0] = Vector3(p1);
00472 detection->point[1] = Vector3(p2);
00473 detection->normal = gnormal;
00474 detection->value = d;
00475 detection->elem.first = e1;
00476 detection->elem.second = e2;
00477 detection->id = i;
00478 ++nc;
00479 }
00480 }
00481 else
00482 {
00483 for (unsigned int i=0; i<x1.size(); i++)
00484 {
00485 DistanceGrid::Coord p1 = x1[i];
00486 DistanceGrid::Coord p2 = translation + rotation*p1;
00487 if (p2[0] < -cubeDim2Margin || p2[0] > cubeDim2Margin ||
00488 p2[1] < -cubeDim2Margin || p2[1] > cubeDim2Margin ||
00489 p2[2] < -cubeDim2Margin || p2[2] > cubeDim2Margin)
00490 continue;
00491
00492
00493 DistanceGrid::Coord normal;
00494 normal[0] = rabs(p2[0]) - cubeDim2;
00495 normal[1] = rabs(p2[1]) - cubeDim2;
00496 normal[2] = rabs(p2[2]) - cubeDim2;
00497
00498 SReal d;
00499
00500 int axis;
00501 if (normal[0] > normal[1])
00502 if (normal[0] > normal[2]) axis = 0;
00503 else axis = 2;
00504 else
00505 if (normal[1] > normal[2]) axis = 1;
00506 else axis = 2;
00507
00508 SReal sign = (p2[axis]<0)?-1.0f:1.0f;
00509 d = normal[axis];
00510 p2[axis] = sign*cubeDim2;
00511 Vector3 gnormal = r2.col(axis) * -sign;
00512
00513
00514
00515 contacts->resize(contacts->size()+1);
00516 DetectionOutput *detection = &*(contacts->end()-1);
00517
00518 detection->point[0] = Vector3(p1);
00519 detection->point[1] = Vector3(p2);
00520 detection->normal = gnormal;
00521 detection->value = d;
00522 detection->elem.first = e1;
00523 detection->elem.second = e2;
00524 detection->id = i;
00525 ++nc;
00526 }
00527 }
00528 }
00529 else
00530 {
00531 for (unsigned int i=0; i<x1.size(); i++)
00532 {
00533 DistanceGrid::Coord p1 = x1[i];
00534 DistanceGrid::Coord p2 = translation + rotation*p1;
00535 #ifdef DEBUG_XFORM
00536 DistanceGrid::Coord p1b = rotation.multTranspose(p2-translation);
00537 DistanceGrid::Coord gp1 = t1+r1*p1;
00538 DistanceGrid::Coord gp2 = t2+r2*p2;
00539 if ((p1b-p1).norm2() > 0.0001f)
00540 std::cerr << "ERROR1a: " << p1 << " -> " << p2 << " -> " << p1b << std::endl;
00541 if ((gp1-gp2).norm2() > 0.0001f)
00542 std::cerr << "ERROR1b: " << p1 << " -> " << gp1 << " " << p2 << " -> " << gp2 << std::endl;
00543 #endif
00544
00545 if (!grid2->inBBox( p2, margin )) continue;
00546 if (!grid2->inGrid( p2 ))
00547 {
00548 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e2.getCollisionModel()->getName()<<std::endl;
00549 continue;
00550 }
00551
00552 SReal d = grid2->interp(p2);
00553 if (d >= margin) continue;
00554
00555 Vector3 grad = grid2->grad(p2);
00556 grad.normalize();
00557
00558
00559
00560 contacts->resize(contacts->size()+1);
00561 DetectionOutput *detection = &*(contacts->end()-1);
00562
00563 detection->point[0] = Vector3(p1);
00564 detection->point[1] = Vector3(p2) - grad * d;
00565 detection->normal = r2 * -grad;
00566 detection->value = d;
00567 detection->elem.first = e1;
00568 detection->elem.second = e2;
00569 detection->id = i;
00570 ++nc;
00571 }
00572 }
00573 }
00574
00575
00576 const DistanceGrid::VecCoord& x2 = grid2->meshPts;
00577 const int i0 = x1.size();
00578 if (!x2.empty() && e2.getCollisionModel()->usePoints.getValue())
00579 {
00580 if (grid1->isCube() && grid2->isCube())
00581 {
00582 const SReal cubeDim1 = grid1->getCubeDim();
00583 const SReal cubeDim1Margin = cubeDim1+margin;
00584
00585 if (face_e1 != FACE_NONE)
00586 {
00587 DistanceGrid::Coord normal;
00588 normal[face_e1/2] = (face_e1&1)?1.0f:-1.0f;
00589 Vector3 gnormal = r1 * normal;
00590
00591 if (gnormal[0] < -0.99f) gnormal = Vector3(-1.0f, 0.0f, 0.0f);
00592 else if (gnormal[0] > 0.99f) gnormal = Vector3( 1.0f, 0.0f, 0.0f);
00593 if (gnormal[1] < -0.99f) gnormal = Vector3( 0.0f,-1.0f, 0.0f);
00594 else if (gnormal[1] > 0.99f) gnormal = Vector3( 0.0f, 1.0f, 0.0f);
00595 if (gnormal[2] < -0.99f) gnormal = Vector3( 0.0f, 0.0f, -1.0f);
00596 else if (gnormal[2] > 0.99f) gnormal = Vector3( 0.0f, 0.0f, 1.0f);
00597 for (unsigned int i=0; i<x2.size(); i++)
00598 {
00599 DistanceGrid::Coord p2 = x2[i];
00600 DistanceGrid::Coord p1 = rotation.multTranspose(p2-translation);
00601 if (p1[0] < -cubeDim1Margin || p1[0] > cubeDim1Margin ||
00602 p1[1] < -cubeDim1Margin || p1[1] > cubeDim1Margin ||
00603 p1[2] < -cubeDim1Margin || p1[2] > cubeDim1Margin)
00604 continue;
00605 double d = p1*normal - cubeDim1;
00606
00607 p1 -= normal * d;
00608
00609 contacts->resize(contacts->size()+1);
00610 DetectionOutput *detection = &*(contacts->end()-1);
00611
00612 detection->point[0] = Vector3(p1);
00613 detection->point[1] = Vector3(p2);
00614 detection->normal = gnormal;
00615 detection->value = d;
00616 detection->elem.first = e1;
00617 detection->elem.second = e2;
00618 detection->id = i + i0;
00619 ++nc;
00620 }
00621 }
00622 else
00623 {
00624 for (unsigned int i=0; i<x2.size(); i++)
00625 {
00626 DistanceGrid::Coord p2 = x2[i];
00627 DistanceGrid::Coord p1 = rotation.multTranspose(p2-translation);
00628 if (p1[0] < -cubeDim1Margin || p1[0] > cubeDim1Margin ||
00629 p1[1] < -cubeDim1Margin || p1[1] > cubeDim1Margin ||
00630 p1[2] < -cubeDim1Margin || p1[2] > cubeDim1Margin)
00631 continue;
00632
00633 DistanceGrid::Coord normal;
00634 normal[0] = rabs(p1[0]) - cubeDim1;
00635 normal[1] = rabs(p1[1]) - cubeDim1;
00636 normal[2] = rabs(p1[2]) - cubeDim1;
00637
00638 SReal d;
00639
00640 int axis;
00641 if (normal[0] > normal[1])
00642 if (normal[0] > normal[2]) axis = 0;
00643 else axis = 2;
00644 else
00645 if (normal[1] > normal[2]) axis = 1;
00646 else axis = 2;
00647
00648 SReal sign = (p1[axis]<0)?-1.0f:1.0f;
00649 d = normal[axis];
00650 p1[axis] = sign*cubeDim1;
00651 Vector3 gnormal = r1.col(axis) * sign;
00652
00653 contacts->resize(contacts->size()+1);
00654 DetectionOutput *detection = &*(contacts->end()-1);
00655
00656 detection->point[0] = Vector3(p1);
00657 detection->point[1] = Vector3(p2);
00658 detection->normal = gnormal;
00659 detection->value = d;
00660 detection->elem.first = e1;
00661 detection->elem.second = e2;
00662 detection->id = i + i0;
00663 ++nc;
00664 }
00665 }
00666 #if 0
00667 #if 0
00668
00669
00671 Vector3 normal = rotation.multTranspose(-translation);
00672
00673 if (rabs(normal[0]) > rabs(normal[1]))
00674 {
00675 if (rabs(normal[0]) > rabs(normal[2]))
00676 normal = Vector3(normal[0]>0.0f?1.0f:-1.0f,0.0f,0.0f);
00677 else
00678 normal = Vector3(0.0f,0.0f,normal[2]>0.0f?1.0f:-1.0f);
00679 }
00680 else
00681 {
00682 if (rabs(normal[1]) > rabs(normal[2]))
00683 normal = Vector3(0.0f,normal[1]>0.0f?1.0f:-1.0f,0.0f);
00684 else
00685 normal = Vector3(0.0f,0.0f,normal[2]>0.0f?1.0f:-1.0f);
00686 }
00687
00688 Vector3 gnormal = r1 * normal;
00689
00690 if (gnormal[2] < -0.99f) gnormal = Vector3(0.0f, 0.0f, -1.0f);
00691 else if (gnormal[2] > 0.99f) gnormal = Vector3(0.0f, 0.0f, 1.0f);
00692 #endif
00693 Vector3 gnormal[3];
00694 for (int i=0;i<3;i++)
00695 {
00696 gnormal[i] = r1.col(i);
00697
00698 if (gnormal[i][0] < -0.99f) gnormal[i] = Vector3(-1.0f, 0.0f, 0.0f);
00699 else if (gnormal[i][0] > 0.99f) gnormal[i] = Vector3( 1.0f, 0.0f, 0.0f);
00700 if (gnormal[i][1] < -0.99f) gnormal[i] = Vector3( 0.0f,-1.0f, 0.0f);
00701 else if (gnormal[i][1] > 0.99f) gnormal[i] = Vector3( 0.0f, 1.0f, 0.0f);
00702 if (gnormal[i][2] < -0.99f) gnormal[i] = Vector3( 0.0f, 0.0f, -1.0f);
00703 else if (gnormal[i][2] > 0.99f) gnormal[i] = Vector3( 0.0f, 0.0f, 1.0f);
00704 }
00705 for (unsigned int i=0; i<x2.size(); i++)
00706 {
00707 DistanceGrid::Coord p2 = x2[i];
00708 DistanceGrid::Coord p1 = rotation.multTranspose(p2-translation);
00709 if (p1[0] < -cubeDim1Margin || p1[0] > cubeDim1Margin ||
00710 p1[1] < -cubeDim1Margin || p1[1] > cubeDim1Margin ||
00711 p1[2] < -cubeDim1Margin || p1[2] > cubeDim1Margin)
00712 continue;
00713
00714 DistanceGrid::Coord p2normal = rotation.multTranspose(grid2->grad(p2));
00715
00716 DistanceGrid::Coord p1normal;
00717
00718 p1normal[0] = (cubeDim1Margin - rabs(p1[0]))/(0.000001+rabs(p2normal[0]));
00719 p1normal[1] = (cubeDim1Margin - rabs(p1[1]))/(0.000001+rabs(p2normal[1]));
00720 p1normal[2] = (cubeDim1Margin - rabs(p1[2]))/(0.000001+rabs(p2normal[2]));
00721
00722 SReal d;
00723 Vector3 normal;
00724
00725 int axis;
00726
00727 if (p1normal[0] < p1normal[1])
00728 {
00729 if (p1normal[0] < p1normal[2])
00730 axis = 0;
00731 else
00732 axis = 2;
00733 }
00734 else
00735 {
00736 if (p1normal[1] < p1normal[2])
00737 axis = 1;
00738 else
00739 axis = 2;
00740 }
00741 if (p1[axis]<0)
00742 {
00743 d = -cubeDim1 - p1[axis];
00744 p1[axis] = -cubeDim1;
00745 normal = -gnormal[axis];
00746 }
00747 else
00748 {
00749 d = p1[axis] - cubeDim1;
00750 p1[axis] = cubeDim1;
00751 normal = gnormal[axis];
00752 }
00753
00754
00755 contacts->resize(contacts->size()+1);
00756 DetectionOutput *detection = &*(contacts->end()-1);
00757
00758 detection->point[0] = Vector3(p1);
00759 detection->point[1] = Vector3(p2);
00760 detection->normal = normal;
00761 detection->value = d;
00762 detection->elem.first = e1;
00763 detection->elem.second = e2;
00764 detection->id = i0+i;
00765 ++nc;
00766 }
00767 #endif
00768 }
00769 else
00770 {
00771 for (unsigned int i=0; i<x2.size(); i++)
00772 {
00773 DistanceGrid::Coord p2 = x2[i];
00774 DistanceGrid::Coord p1 = rotation.multTranspose(p2-translation);
00775 #ifdef DEBUG_XFORM
00776 DistanceGrid::Coord p2b = translation + rotation*p1;
00777 DistanceGrid::Coord gp1 = t1+r1*p1;
00778 DistanceGrid::Coord gp2 = t2+r2*p2;
00779 if ((p2b-p2).norm2() > 0.0001f)
00780 std::cerr << "ERROR2a: " << p2 << " -> " << p1 << " -> " << p2b << std::endl;
00781 else if ((gp1-gp2).norm2() > 0.0001f)
00782 std::cerr << "ERROR2b: " << p1 << " -> " << gp1 << " " << p2 << " -> " << gp2 << std::endl;
00783 #endif
00784
00785 if (!grid1->inBBox( p1, margin )) continue;
00786 if (!grid1->inGrid( p1 ))
00787 {
00788 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e1.getCollisionModel()->getName()<<std::endl;
00789 continue;
00790 }
00791
00792 SReal d = grid1->interp(p1);
00793 if (d >= margin) continue;
00794
00795 Vector3 grad = grid1->grad(p1);
00796 grad.normalize();
00797
00798
00799
00800 contacts->resize(contacts->size()+1);
00801 DetectionOutput *detection = &*(contacts->end()-1);
00802
00803 detection->point[0] = Vector3(p1) - grad * d;
00804 detection->point[1] = Vector3(p2);
00805 detection->normal = r1 * grad;
00806 detection->value = d;
00807 detection->elem.first = e1;
00808 detection->elem.second = e2;
00809 detection->id = i0+i;
00810 ++nc;
00811 }
00812 }
00813 }
00814 return nc;
00815 }
00816
00817 bool DiscreteIntersection::testIntersection(RigidDistanceGridCollisionElement&, Point&)
00818 {
00819 return true;
00820 }
00821
00822 int DiscreteIntersection::computeIntersection(RigidDistanceGridCollisionElement& e1, Point& e2, OutputVector* contacts)
00823 {
00824 DistanceGrid* grid1 = e1.getGrid();
00825 bool useXForm = e1.isTransformed();
00826 const Vector3& t1 = e1.getTranslation();
00827 const Matrix3& r1 = e1.getRotation();
00828
00829 const double d0 = e1.getProximity() + e2.getProximity() + getContactDistance();
00830 const SReal margin = 0.001f + (SReal)d0;
00831
00832 Vector3 p2 = e2.p();
00833 DistanceGrid::Coord p1;
00834
00835 if (useXForm)
00836 {
00837 p1 = r1.multTranspose(p2-t1);
00838 }
00839 else p1 = p2;
00840
00841 if (!grid1->inBBox( p1, margin )) return 0;
00842 if (!grid1->inGrid( p1 ))
00843 {
00844 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e1.getCollisionModel()->getName()<<std::endl;
00845 return 0;
00846 }
00847
00848 SReal d = grid1->interp(p1);
00849 if (d >= margin) return 0;
00850
00851 Vector3 grad = grid1->grad(p1);
00852 grad.normalize();
00853
00854
00855
00856 contacts->resize(contacts->size()+1);
00857 DetectionOutput *detection = &*(contacts->end()-1);
00858
00859 detection->point[0] = Vector3(p1) - grad * d;
00860 detection->point[1] = Vector3(p2);
00861 detection->normal = (useXForm) ? r1 * grad : grad;
00862 detection->value = d - d0;
00863 detection->elem.first = e1;
00864 detection->elem.second = e2;
00865 detection->id = e2.getIndex();
00866 return 1;
00867 }
00868
00869 bool DiscreteIntersection::testIntersection(RigidDistanceGridCollisionElement&, Triangle&)
00870 {
00871 return true;
00872 }
00873
00874 int DiscreteIntersection::computeIntersection(RigidDistanceGridCollisionElement& e1, Triangle& e2, OutputVector* contacts)
00875 {
00876 const int f2 = e2.flags();
00877 if (!(f2&TriangleModel::FLAG_POINTS)) return 0;
00878 DistanceGrid* grid1 = e1.getGrid();
00879 bool useXForm = e1.isTransformed();
00880 const Vector3& t1 = e1.getTranslation();
00881 const Matrix3& r1 = e1.getRotation();
00882
00883 const double d0 = e1.getProximity() + e2.getProximity() + getContactDistance();
00884 const SReal margin = 0.001f + (SReal)d0;
00885
00886 if (f2&TriangleModel::FLAG_P1)
00887 {
00888 Vector3 p2 = e2.p1();
00889 DistanceGrid::Coord p1;
00890
00891 if (useXForm)
00892 {
00893 p1 = r1.multTranspose(p2-t1);
00894 }
00895 else p1 = p2;
00896
00897 if (grid1->inBBox( p1, margin ))
00898 {
00899 if (!grid1->inGrid( p1 ))
00900 {
00901 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e1.getCollisionModel()->getName()<<std::endl;
00902 }
00903 else
00904 {
00905 SReal d = grid1->interp(p1);
00906 if (d >= margin) return 0;
00907
00908 Vector3 grad = grid1->grad(p1);
00909 grad.normalize();
00910
00911
00912
00913 contacts->resize(contacts->size()+1);
00914 DetectionOutput *detection = &*(contacts->end()-1);
00915
00916 detection->point[0] = Vector3(p1) - grad * d;
00917 detection->point[1] = Vector3(p2);
00918 detection->normal = (useXForm) ? r1 * grad : grad;
00919 detection->value = d - d0;
00920 detection->elem.first = e1;
00921 detection->elem.second = e2;
00922 detection->id = e2.getIndex()*3+0;
00923 }
00924 }
00925 }
00926
00927 if (f2&TriangleModel::FLAG_P2)
00928 {
00929 Vector3 p2 = e2.p2();
00930 DistanceGrid::Coord p1;
00931
00932 if (useXForm)
00933 {
00934 p1 = r1.multTranspose(p2-t1);
00935 }
00936 else p1 = p2;
00937
00938 if (grid1->inBBox( p1, margin ))
00939 {
00940 if (!grid1->inGrid( p1 ))
00941 {
00942 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e1.getCollisionModel()->getName()<<std::endl;
00943 }
00944 else
00945 {
00946 SReal d = grid1->interp(p1);
00947 if (d >= margin) return 0;
00948
00949 Vector3 grad = grid1->grad(p1);
00950 grad.normalize();
00951
00952
00953
00954 contacts->resize(contacts->size()+1);
00955 DetectionOutput *detection = &*(contacts->end()-1);
00956
00957 detection->point[0] = Vector3(p1) - grad * d;
00958 detection->point[1] = Vector3(p2);
00959 detection->normal = (useXForm) ? r1 * grad : grad;
00960 detection->value = d - d0;
00961 detection->elem.first = e1;
00962 detection->elem.second = e2;
00963 detection->id = e2.getIndex()*3+1;
00964 }
00965 }
00966 }
00967
00968 if (f2&TriangleModel::FLAG_P3)
00969 {
00970 Vector3 p2 = e2.p3();
00971 DistanceGrid::Coord p1;
00972
00973 if (useXForm)
00974 {
00975 p1 = r1.multTranspose(p2-t1);
00976 }
00977 else p1 = p2;
00978
00979 if (grid1->inBBox( p1, margin ))
00980 {
00981 if (!grid1->inGrid( p1 ))
00982 {
00983 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e1.getCollisionModel()->getName()<<std::endl;
00984 }
00985 else
00986 {
00987 SReal d = grid1->interp(p1);
00988 if (d >= margin) return 0;
00989
00990 Vector3 grad = grid1->grad(p1);
00991 grad.normalize();
00992
00993
00994
00995 contacts->resize(contacts->size()+1);
00996 DetectionOutput *detection = &*(contacts->end()-1);
00997
00998 detection->point[0] = Vector3(p1) - grad * d;
00999 detection->point[1] = Vector3(p2);
01000 detection->normal = (useXForm) ? r1 * grad : grad;
01001 detection->value = d - d0;
01002 detection->elem.first = e1;
01003 detection->elem.second = e2;
01004 detection->id = e2.getIndex()*3+2;
01005 }
01006 }
01007 }
01008 return 1;
01009 }
01010
01011 bool DiscreteIntersection::testIntersection(Ray& , RigidDistanceGridCollisionElement& )
01012 {
01013 return true;
01014 }
01015
01016 int DiscreteIntersection::computeIntersection(Ray& e2, RigidDistanceGridCollisionElement& e1, OutputVector* contacts)
01017 {
01018 Vector3 rayOrigin(e2.origin());
01019 Vector3 rayDirection(e2.direction());
01020 const double rayLength = e2.l();
01021
01022 int nc = 0;
01023 DistanceGrid* grid1 = e1.getGrid();
01024 bool useXForm = e1.isTransformed();
01025
01026 if (useXForm)
01027 {
01028 const Vector3& t1 = e1.getTranslation();
01029 const Matrix3& r1 = e1.getRotation();
01030 rayOrigin = r1.multTranspose(rayOrigin-t1);
01031 rayDirection = r1.multTranspose(rayDirection);
01032
01033 }
01034
01035 double l0 = 0;
01036 double l1 = rayLength;
01037 Vector3 r0 = rayOrigin;
01038 Vector3 r1 = rayOrigin + rayDirection*l1;
01039
01040 DistanceGrid::Coord bbmin = grid1->getBBMin(), bbmax = grid1->getBBMax();
01041
01042 for (int c=0;c<3 && l1>l0;c++)
01043 {
01044 if (rayDirection[c] > 0)
01045 {
01046
01047 if (r1[c] < bbmin[c] || r0[c] > bbmax[c])
01048 { l1 = 0; break; }
01049 if (r0[c] < bbmin[c])
01050 {
01051
01052 double l = (bbmin[c]-rayOrigin[c]) / rayDirection[c];
01053 if(l0 < l)
01054 {
01055 l0 = l;
01056 r0 = rayOrigin + rayDirection*l0;
01057 }
01058 }
01059 if (r1[c] > bbmax[c])
01060 {
01061
01062 double l = (bbmax[c]-rayOrigin[c]) / rayDirection[c];
01063 if(l1 > l)
01064 {
01065 l1 = l;
01066 r1 = rayOrigin + rayDirection*l1;
01067 }
01068 }
01069 }
01070 else
01071 {
01072
01073 if (r0[c] < bbmin[c] || r1[c] > bbmax[c])
01074 { l1 = 0; break; }
01075 if (r0[c] > bbmax[c])
01076 {
01077
01078 double l = (bbmax[c]-rayOrigin[c]) / rayDirection[c];
01079 if(l0 < l)
01080 {
01081 l0 = l;
01082 r0 = rayOrigin + rayDirection*l0;
01083 }
01084 }
01085 if (r1[c] < bbmin[c])
01086 {
01087
01088 double l = (bbmin[c]-rayOrigin[c]) / rayDirection[c];
01089 if(l1 > l)
01090 {
01091 l1 = l;
01092 r1 = rayOrigin + rayDirection*l1;
01093 }
01094 }
01095 }
01096
01097 }
01098
01099 if (l0 < l1)
01100 {
01101 Vector3 p = rayOrigin + rayDirection*l0;
01102 double dist = grid1->interp(p);
01103 double epsilon = grid1->getCellWidth().norm()*0.1f;
01104 while (l0 < l1 && (dist > epsilon || dist < -epsilon))
01105 {
01106 l0 += dist;
01107 p = rayOrigin + rayDirection*l0;
01108 dist = grid1->interp(p);
01109
01110 }
01111 if (dist < epsilon)
01112 {
01113
01114 contacts->resize(contacts->size()+1);
01115 DetectionOutput *detection = &*(contacts->end()-1);
01116
01117 detection->point[0] = e2.origin() + e2.direction()*l0;
01118 detection->point[1] = p;
01119 detection->normal = e2.direction();
01120 detection->value = dist;
01121 detection->elem.first = e2;
01122 detection->elem.second = e1;
01123 detection->id = e2.getIndex();
01124 ++nc;
01125 }
01126 }
01127 return nc;
01128 }
01129
01130 bool DiscreteIntersection::testIntersection(FFDDistanceGridCollisionElement&, RigidDistanceGridCollisionElement&)
01131 {
01132 return true;
01133 }
01134
01135 int DiscreteIntersection::computeIntersection(FFDDistanceGridCollisionElement& e1, RigidDistanceGridCollisionElement& e2, OutputVector* contacts)
01136 {
01137 int nc = 0;
01138 DistanceGrid* grid1 = e1.getGrid();
01139 DistanceGrid* grid2 = e2.getGrid();
01140 FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex());
01141 bool useXForm = e2.isTransformed();
01142
01143
01144 const Vector3& t2 = e2.getTranslation();
01145 const Matrix3& r2 = e2.getRotation();
01146
01147 const double d0 = e1.getProximity() + e2.getProximity();
01148 const SReal margin = 0.001f + (SReal)d0;
01149
01150
01151 Vec3f translation;
01152 Mat3x3f rotation;
01153
01154 if (useXForm)
01155 {
01156 translation = r2.multTranspose(-t2);
01157 rotation = r2; rotation.transpose();
01158 }
01159 else rotation.identity();
01160
01161 const DistanceGrid::Coord center2 = translation + rotation*c1.center;
01162 const SReal radius2 = c1.radius*c1.radius;
01163 const DistanceGrid::VecCoord& x2 = grid2->meshPts;
01164 const int i0 = x2.size();
01165
01166 if (e1.getCollisionModel()->usePoints.getValue())
01167 {
01168 if (grid2->inBBox( center2, margin + c1.radius ))
01169 {
01170 c1.updatePoints();
01171 const sofa::helper::vector<DistanceGrid::Coord>& x1 = c1.deformedPoints;
01172 for (unsigned int i=0; i<x1.size(); i++)
01173 {
01174 DistanceGrid::Coord p1 = x1[i];
01175 DistanceGrid::Coord p2 = translation + rotation*p1;
01176
01177 if (!grid2->inBBox( p2, margin )) continue;
01178 if (!grid2->inGrid( p2 ))
01179 {
01180 std::cerr << "WARNING: margin less than "<<margin<<" in DistanceGrid "<<e2.getCollisionModel()->getName()<<std::endl;
01181 continue;
01182 }
01183
01184 SReal d = grid2->interp(p2);
01185 if (d >= margin) continue;
01186
01187 Vector3 grad = grid2->grad(p2);
01188 grad.normalize();
01189
01190
01191
01192 contacts->resize(contacts->size()+1);
01193 DetectionOutput *detection = &*(contacts->end()-1);
01194
01195 detection->point[0] = grid1->meshPts[c1.points[i].index];
01196 detection->point[1] = Vector3(p2) - grad * d;
01197 detection->normal = r2 * -grad;
01198 detection->value = d - d0;
01199 detection->elem.first = e1;
01200 detection->elem.second = e2;
01201 detection->id = i0 + c1.points[i].index;
01202 ++nc;
01203 }
01204 }
01205 }
01206
01207
01208
01209 if (!x2.empty() && e2.getCollisionModel()->usePoints.getValue())
01210 {
01211 const SReal cubesize = c1.invDP.norm();
01212 for (unsigned int i=0; i<x2.size(); i++)
01213 {
01214 DistanceGrid::Coord p2 = x2[i];
01215 if ((p2-center2).norm2() >= radius2) continue;
01216 DistanceGrid::Coord p1 = rotation.multTranspose(p2-translation);
01217
01218 {
01219 c1.updateFaces();
01220
01221 DistanceGrid::Coord b = c1.undeform0(p1);
01222
01223
01224 int iter;
01225 SReal err1 = 1000.0f;
01226 for(iter=0; iter<5; ++iter)
01227 {
01228 DistanceGrid::Coord pdeform = c1.deform(b);
01229 DistanceGrid::Coord diff = p1-pdeform;
01230 SReal err = diff.norm();
01231 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01232 if (b[0] < -berr || b[0] > 1+berr
01233 || b[1] < -berr || b[1] > 1+berr
01234 || b[2] < -berr || b[2] > 1+berr)
01235 break;
01236 if (iter>3)
01237 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01238 if (err < 0.005f)
01239 {
01240 if (b[0] > 0.001f && b[0] < 0.999f
01241 && b[1] > 0.001f && b[1] < 0.999f
01242 && b[2] > 0.001f && b[2] < 0.999f)
01243 {
01244 DistanceGrid::Coord pinit = c1.initpos(b);
01245 SReal d = grid1->interp(pinit);
01246 if (d < margin)
01247 {
01248 DistanceGrid::Coord grad = grid1->grad(pinit);
01249 grad.normalize();
01250 pinit -= grad*d;
01251 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01252 grad.normalize();
01253
01254 contacts->resize(contacts->size()+1);
01255 DetectionOutput *detection = &*(contacts->end()-1);
01256
01257 detection->point[0] = Vector3(pinit);
01258 detection->point[1] = Vector3(p2);
01259 detection->normal = Vector3(grad);
01260 detection->value = d - d0;
01261 detection->elem.first = e1;
01262 detection->elem.second = e2;
01263 detection->id = i;
01264 ++nc;
01265 }
01266 }
01267 break;
01268 }
01269 err1 = err;
01270 SReal d = grid1->interp(c1.initpos(b));
01271 if (d*0.5f - err > margin)
01272 break;
01273
01274
01275 b += c1.undeformDir( b, diff );
01276 }
01277 if (iter == 5)
01278 {
01279 if (b[0] > 0.001f && b[0] < 0.999f
01280 && b[1] > 0.001f && b[1] < 0.999f
01281 && b[2] > 0.001f && b[2] < 0.999f)
01282 std::cerr << "ERROR: FFD-Rigid collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01283 }
01284 }
01285 }
01286 }
01287 return nc;
01288 }
01289
01290
01291 bool DiscreteIntersection::testIntersection(FFDDistanceGridCollisionElement&, FFDDistanceGridCollisionElement&)
01292 {
01293 return true;
01294 }
01295
01296 int DiscreteIntersection::computeIntersection(FFDDistanceGridCollisionElement& e1, FFDDistanceGridCollisionElement& e2, OutputVector* contacts)
01297 {
01298 int nc = 0;
01299 DistanceGrid* grid1 = e1.getGrid();
01300 DistanceGrid* grid2 = e2.getGrid();
01301 FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex());
01302 FFDDistanceGridCollisionModel::DeformedCube& c2 = e2.getCollisionModel()->getDeformCube(e2.getIndex());
01303 const bool usePoints1 = e1.getCollisionModel()->usePoints.getValue();
01304 const bool usePoints2 = e2.getCollisionModel()->usePoints.getValue();
01305
01306 if (!usePoints1 && !usePoints2) return 0;
01307
01308 const double d0 = e1.getProximity() + e2.getProximity();
01309 const SReal margin = 0.001f + (SReal)d0;
01310
01311 if ((c2.center - c1.center).norm2() > (c1.radius+c2.radius)*(c1.radius+c2.radius))
01312 return 0;
01313
01314 int i0 = grid1->meshPts.size();
01315 if (usePoints1)
01316 {
01317 c1.updatePoints();
01318 c2.updateFaces();
01319 const SReal cubesize = c2.invDP.norm();
01320 const sofa::helper::vector<DistanceGrid::Coord>& x1 = c1.deformedPoints;
01321 for (unsigned int i=0; i<x1.size(); i++)
01322 {
01323 DistanceGrid::Coord p2 = x1[i];
01324
01325
01326 DistanceGrid::Coord b = c2.undeform0(p2);
01327
01328
01329 int iter;
01330 SReal err1 = 1000.0f;
01331 for(iter=0; iter<5; ++iter)
01332 {
01333 DistanceGrid::Coord pdeform = c2.deform(b);
01334 DistanceGrid::Coord diff = p2-pdeform;
01335 SReal err = diff.norm();
01336 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01337 if (b[0] < -berr || b[0] > 1+berr
01338 || b[1] < -berr || b[1] > 1+berr
01339 || b[2] < -berr || b[2] > 1+berr)
01340 break;
01341 if (iter>3)
01342 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid2->interp(c2.initpos(b))<<"\n";
01343 if (err < 0.005f)
01344 {
01345 if (b[0] > 0.001f && b[0] < 0.999f
01346 && b[1] > 0.001f && b[1] < 0.999f
01347 && b[2] > 0.001f && b[2] < 0.999f)
01348 {
01349 DistanceGrid::Coord pinit = c2.initpos(b);
01350 SReal d = grid2->interp(pinit);
01351 if (d < margin)
01352 {
01353 DistanceGrid::Coord grad = grid2->grad(pinit);
01354 grad.normalize();
01355 pinit -= grad*d;
01356 grad = c2.deformDir(c2.baryCoords(pinit),grad);
01357 grad.normalize();
01358
01359 contacts->resize(contacts->size()+1);
01360 DetectionOutput *detection = &*(contacts->end()-1);
01361
01362 detection->point[0] = Vector3(grid1->meshPts[c1.points[i].index]);
01363 detection->point[1] = Vector3(pinit);
01364 detection->normal = Vector3(-grad);
01365 detection->value = d - d0;
01366 detection->elem.first = e1;
01367 detection->elem.second = e2;
01368 detection->id = c1.points[i].index;
01369 ++nc;
01370 }
01371 }
01372 break;
01373 }
01374 err1 = err;
01375 SReal d = grid2->interp(c2.initpos(b));
01376 if (d*0.5f - err > margin)
01377 break;
01378
01379
01380 b += c2.undeformDir( b, diff );
01381 }
01382 if (iter == 5)
01383 {
01384 if (b[0] > 0.001f && b[0] < 0.999f
01385 && b[1] > 0.001f && b[1] < 0.999f
01386 && b[2] > 0.001f && b[2] < 0.999f)
01387 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p2 = "<<p2<<" b = "<<b<<" c000 = "<<c2.corners[0]<<" c100 = "<<c2.corners[1]<<" c010 = "<<c2.corners[2]<<" c110 = "<<c2.corners[3]<<" c001 = "<<c2.corners[4]<<" c101 = "<<c2.corners[5]<<" c011 = "<<c2.corners[6]<<" c111 = "<<c2.corners[7]<<" pinit = "<<c2.initpos(b)<<" pdeform = "<<c2.deform(b)<<" err = "<<err1<<std::endl;
01388 }
01389 }
01390 }
01391 if (usePoints2)
01392 {
01393 c2.updatePoints();
01394 c1.updateFaces();
01395 const SReal cubesize = c1.invDP.norm();
01396 const sofa::helper::vector<DistanceGrid::Coord>& x2 = c2.deformedPoints;
01397 for (unsigned int i=0; i<x2.size(); i++)
01398 {
01399 DistanceGrid::Coord p1 = x2[i];
01400
01401
01402 DistanceGrid::Coord b = c1.undeform0(p1);
01403
01404
01405 int iter;
01406 SReal err1 = 1000.0f;
01407 for(iter=0; iter<5; ++iter)
01408 {
01409 DistanceGrid::Coord pdeform = c1.deform(b);
01410 DistanceGrid::Coord diff = p1-pdeform;
01411 SReal err = diff.norm();
01412 if (iter>3)
01413 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01414 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01415 if (b[0] < -berr || b[0] > 1+berr
01416 || b[1] < -berr || b[1] > 1+berr
01417 || b[2] < -berr || b[2] > 1+berr)
01418 break;
01419 if (err < 0.005f)
01420 {
01421 if (b[0] > 0.001f && b[0] < 0.999f
01422 && b[1] > 0.001f && b[1] < 0.999f
01423 && b[2] > 0.001f && b[2] < 0.999f)
01424 {
01425 DistanceGrid::Coord pinit = c1.initpos(b);
01426 SReal d = grid1->interp(pinit);
01427 if (d < margin)
01428 {
01429 DistanceGrid::Coord grad = grid1->grad(pinit);
01430 grad.normalize();
01431 pinit -= grad*d;
01432 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01433 grad.normalize();
01434
01435 contacts->resize(contacts->size()+1);
01436 DetectionOutput *detection = &*(contacts->end()-1);
01437
01438 detection->point[0] = Vector3(pinit);
01439 detection->point[1] = Vector3(grid2->meshPts[c2.points[i].index]);
01440 detection->normal = Vector3(grad);
01441 detection->value = d - d0;
01442 detection->elem.first = e1;
01443 detection->elem.second = e2;
01444 detection->id = i0+c2.points[i].index;
01445 ++nc;
01446 }
01447 }
01448 break;
01449 }
01450 err1 = err;
01451 SReal d = grid1->interp(c1.initpos(b));
01452 if (d*0.5f - err > margin)
01453 break;
01454
01455
01456 b += c1.undeformDir( b, diff );
01457 }
01458 if (iter == 5)
01459 {
01460 if (b[0] > 0.001f && b[0] < 0.999f
01461 && b[1] > 0.001f && b[1] < 0.999f
01462 && b[2] > 0.001f && b[2] < 0.999f)
01463 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01464 }
01465 }
01466 }
01467 return nc;
01468 }
01469
01470 bool DiscreteIntersection::testIntersection(FFDDistanceGridCollisionElement&, Point&)
01471 {
01472 return true;
01473 }
01474
01475 int DiscreteIntersection::computeIntersection(FFDDistanceGridCollisionElement& e1, Point& e2, OutputVector* contacts)
01476 {
01477
01478 DistanceGrid* grid1 = e1.getGrid();
01479 FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex());
01480
01481 const double d0 = e1.getProximity() + e2.getProximity() + getContactDistance();
01482 const SReal margin = 0.001f + (SReal)d0;
01483
01484 c1.updateFaces();
01485 const SReal cubesize = c1.invDP.norm();
01486 int nc = 0;
01487
01488 Vector3 p2 = e2.p();
01489 DistanceGrid::Coord p1 = p2;
01490
01491
01492 DistanceGrid::Coord b = c1.undeform0(p1);
01493
01494
01495 int iter;
01496 SReal err1 = 1000.0f;
01497 for(iter=0; iter<5; ++iter)
01498 {
01499 DistanceGrid::Coord pdeform = c1.deform(b);
01500 DistanceGrid::Coord diff = p1-pdeform;
01501 SReal err = diff.norm();
01502 if (iter>3)
01503 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01504 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01505 if (b[0] < -berr || b[0] > 1+berr
01506 || b[1] < -berr || b[1] > 1+berr
01507 || b[2] < -berr || b[2] > 1+berr)
01508 break;
01509 if (err < 0.005f)
01510 {
01511 if (b[0] > 0.001f && b[0] < 0.999f
01512 && b[1] > 0.001f && b[1] < 0.999f
01513 && b[2] > 0.001f && b[2] < 0.999f)
01514 {
01515 DistanceGrid::Coord pinit = c1.initpos(b);
01516 SReal d = grid1->interp(pinit);
01517 if (d < margin)
01518 {
01519 DistanceGrid::Coord grad = grid1->grad(pinit);
01520 grad.normalize();
01521 pinit -= grad*d;
01522 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01523 grad.normalize();
01524
01525 contacts->resize(contacts->size()+1);
01526 DetectionOutput *detection = &*(contacts->end()-1);
01527
01528 detection->point[0] = Vector3(pinit);
01529 detection->point[1] = Vector3(p2);
01530 detection->normal = Vector3(grad);
01531 detection->value = d - d0;
01532 detection->elem.first = e1;
01533 detection->elem.second = e2;
01534 detection->id = e2.getIndex();
01535 ++nc;
01536 }
01537 }
01538 break;
01539 }
01540 err1 = err;
01541 SReal d = grid1->interp(c1.initpos(b));
01542 if (d*0.5f - err > margin)
01543 break;
01544
01545
01546 b += c1.undeformDir( b, diff );
01547 }
01548 if (iter == 5)
01549 {
01550 if (b[0] > 0.001f && b[0] < 0.999f
01551 && b[1] > 0.001f && b[1] < 0.999f
01552 && b[2] > 0.001f && b[2] < 0.999f)
01553 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01554 }
01555
01556 return nc;
01557 }
01558
01559 bool DiscreteIntersection::testIntersection(FFDDistanceGridCollisionElement&, Triangle&)
01560 {
01561 return true;
01562 }
01563
01564 int DiscreteIntersection::computeIntersection(FFDDistanceGridCollisionElement& e1, Triangle& e2, OutputVector* contacts)
01565 {
01566 const int f2 = e2.flags();
01567 if (!(f2&TriangleModel::FLAG_POINTS)) return 0;
01568
01569 DistanceGrid* grid1 = e1.getGrid();
01570 FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex());
01571
01572 const double d0 = e1.getProximity() + e2.getProximity() + getContactDistance();
01573 const SReal margin = 0.001f + (SReal)d0;
01574
01575 c1.updateFaces();
01576 const SReal cubesize = c1.invDP.norm();
01577 int nc = 0;
01578
01579 if (f2&TriangleModel::FLAG_P1)
01580 {
01581 Vector3 p2 = e2.p1();
01582 DistanceGrid::Coord p1 = p2;
01583
01584
01585 DistanceGrid::Coord b = c1.undeform0(p1);
01586
01587
01588 int iter;
01589 SReal err1 = 1000.0f;
01590 for(iter=0; iter<5; ++iter)
01591 {
01592 DistanceGrid::Coord pdeform = c1.deform(b);
01593 DistanceGrid::Coord diff = p1-pdeform;
01594 SReal err = diff.norm();
01595 if (iter>3)
01596 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01597 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01598 if (b[0] < -berr || b[0] > 1+berr
01599 || b[1] < -berr || b[1] > 1+berr
01600 || b[2] < -berr || b[2] > 1+berr)
01601 break;
01602 if (err < 0.005f)
01603 {
01604 if (b[0] > 0.001f && b[0] < 0.999f
01605 && b[1] > 0.001f && b[1] < 0.999f
01606 && b[2] > 0.001f && b[2] < 0.999f)
01607 {
01608 DistanceGrid::Coord pinit = c1.initpos(b);
01609 SReal d = grid1->interp(pinit);
01610 if (d < margin)
01611 {
01612 DistanceGrid::Coord grad = grid1->grad(pinit);
01613 grad.normalize();
01614 pinit -= grad*d;
01615 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01616 grad.normalize();
01617
01618 contacts->resize(contacts->size()+1);
01619 DetectionOutput *detection = &*(contacts->end()-1);
01620
01621 detection->point[0] = Vector3(pinit);
01622 detection->point[1] = Vector3(p2);
01623 detection->normal = Vector3(grad);
01624 detection->value = d - d0;
01625 detection->elem.first = e1;
01626 detection->elem.second = e2;
01627 detection->id = e2.getIndex()*3+0;
01628 ++nc;
01629 }
01630 }
01631 break;
01632 }
01633 err1 = err;
01634 SReal d = grid1->interp(c1.initpos(b));
01635 if (d*0.5f - err > margin)
01636 break;
01637
01638
01639 b += c1.undeformDir( b, diff );
01640 }
01641 if (iter == 5)
01642 {
01643 if (b[0] > 0.001f && b[0] < 0.999f
01644 && b[1] > 0.001f && b[1] < 0.999f
01645 && b[2] > 0.001f && b[2] < 0.999f)
01646 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01647 }
01648 }
01649
01650 if (f2&TriangleModel::FLAG_P2)
01651 {
01652 Vector3 p2 = e2.p2();
01653 DistanceGrid::Coord p1 = p2;
01654
01655
01656 DistanceGrid::Coord b = c1.undeform0(p1);
01657
01658
01659 int iter;
01660 SReal err1 = 1000.0f;
01661 for(iter=0; iter<5; ++iter)
01662 {
01663 DistanceGrid::Coord pdeform = c1.deform(b);
01664 DistanceGrid::Coord diff = p1-pdeform;
01665 SReal err = diff.norm();
01666 if (iter>3)
01667 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01668 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01669 if (b[0] < -berr || b[0] > 1+berr
01670 || b[1] < -berr || b[1] > 1+berr
01671 || b[2] < -berr || b[2] > 1+berr)
01672 break;
01673 if (err < 0.005f)
01674 {
01675 if (b[0] > 0.001f && b[0] < 0.999f
01676 && b[1] > 0.001f && b[1] < 0.999f
01677 && b[2] > 0.001f && b[2] < 0.999f)
01678 {
01679 DistanceGrid::Coord pinit = c1.initpos(b);
01680 SReal d = grid1->interp(pinit);
01681 if (d < margin)
01682 {
01683 DistanceGrid::Coord grad = grid1->grad(pinit);
01684 grad.normalize();
01685 pinit -= grad*d;
01686 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01687 grad.normalize();
01688
01689 contacts->resize(contacts->size()+1);
01690 DetectionOutput *detection = &*(contacts->end()-1);
01691
01692 detection->point[0] = Vector3(pinit);
01693 detection->point[1] = Vector3(p2);
01694 detection->normal = Vector3(grad);
01695 detection->value = d - d0;
01696 detection->elem.first = e1;
01697 detection->elem.second = e2;
01698 detection->id = e2.getIndex()*3+1;
01699 ++nc;
01700 }
01701 }
01702 break;
01703 }
01704 err1 = err;
01705 SReal d = grid1->interp(c1.initpos(b));
01706 if (d*0.5f - err > margin)
01707 break;
01708
01709
01710 b += c1.undeformDir( b, diff );
01711 }
01712 if (iter == 5)
01713 {
01714 if (b[0] > 0.001f && b[0] < 0.999f
01715 && b[1] > 0.001f && b[1] < 0.999f
01716 && b[2] > 0.001f && b[2] < 0.999f)
01717 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01718 }
01719 }
01720
01721 if (f2&TriangleModel::FLAG_P3)
01722 {
01723 Vector3 p2 = e2.p3();
01724 DistanceGrid::Coord p1 = p2;
01725
01726
01727 DistanceGrid::Coord b = c1.undeform0(p1);
01728
01729
01730 int iter;
01731 SReal err1 = 1000.0f;
01732 for(iter=0; iter<5; ++iter)
01733 {
01734 DistanceGrid::Coord pdeform = c1.deform(b);
01735 DistanceGrid::Coord diff = p1-pdeform;
01736 SReal err = diff.norm();
01737 if (iter>3)
01738 std::cout << "Iter"<<iter<<": "<<err1<<" -> "<<err<<" b = "<<b<<" diff = "<<diff<<" d = "<<grid1->interp(c1.initpos(b))<<"\n";
01739 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01740 if (b[0] < -berr || b[0] > 1+berr
01741 || b[1] < -berr || b[1] > 1+berr
01742 || b[2] < -berr || b[2] > 1+berr)
01743 break;
01744 if (err < 0.005f)
01745 {
01746 if (b[0] > 0.001f && b[0] < 0.999f
01747 && b[1] > 0.001f && b[1] < 0.999f
01748 && b[2] > 0.001f && b[2] < 0.999f)
01749 {
01750 DistanceGrid::Coord pinit = c1.initpos(b);
01751 SReal d = grid1->interp(pinit);
01752 if (d < margin)
01753 {
01754 DistanceGrid::Coord grad = grid1->grad(pinit);
01755 grad.normalize();
01756 pinit -= grad*d;
01757 grad = c1.deformDir(c1.baryCoords(pinit),grad);
01758 grad.normalize();
01759
01760 contacts->resize(contacts->size()+1);
01761 DetectionOutput *detection = &*(contacts->end()-1);
01762
01763 detection->point[0] = Vector3(pinit);
01764 detection->point[1] = Vector3(p2);
01765 detection->normal = Vector3(grad);
01766 detection->value = d - d0;
01767 detection->elem.first = e1;
01768 detection->elem.second = e2;
01769 detection->id = e2.getIndex()*3+2;
01770 ++nc;
01771 }
01772 }
01773 break;
01774 }
01775 err1 = err;
01776 SReal d = grid1->interp(c1.initpos(b));
01777 if (d*0.5f - err > margin)
01778 break;
01779
01780
01781 b += c1.undeformDir( b, diff );
01782 }
01783 if (iter == 5)
01784 {
01785 if (b[0] > 0.001f && b[0] < 0.999f
01786 && b[1] > 0.001f && b[1] < 0.999f
01787 && b[2] > 0.001f && b[2] < 0.999f)
01788 std::cerr << "ERROR: FFD-FFD collision failed to converge to undeformed point: p1 = "<<p1<<" b = "<<b<<" c000 = "<<c1.corners[0]<<" c100 = "<<c1.corners[1]<<" c010 = "<<c1.corners[2]<<" c110 = "<<c1.corners[3]<<" c001 = "<<c1.corners[4]<<" c101 = "<<c1.corners[5]<<" c011 = "<<c1.corners[6]<<" c111 = "<<c1.corners[7]<<" pinit = "<<c1.initpos(b)<<" pdeform = "<<c1.deform(b)<<" err = "<<err1<<std::endl;
01789 }
01790 }
01791 return nc;
01792 }
01793
01794 bool DiscreteIntersection::testIntersection(Ray& , FFDDistanceGridCollisionElement& )
01795 {
01796 return true;
01797 }
01798
01799 int DiscreteIntersection::computeIntersection(Ray& e2, FFDDistanceGridCollisionElement& e1, OutputVector* contacts)
01800 {
01801 Vector3 rayOrigin(e2.origin());
01802 Vector3 rayDirection(e2.direction());
01803 const double rayLength = e2.l();
01804
01805 DistanceGrid* grid1 = e1.getGrid();
01806 FFDDistanceGridCollisionModel::DeformedCube& c1 = e1.getCollisionModel()->getDeformCube(e1.getIndex());
01807
01808
01809 const Vector3 center1 = c1.center;
01810
01811 const double radius1 = c1.radius;
01812
01813 const Vector3 tmp = center1 - rayOrigin;
01814 double rayPos = tmp*rayDirection;
01815 const double dist2 = tmp.norm2() - (rayPos*rayPos);
01816 if (dist2 >= (radius1*radius1))
01817 return 0;
01818
01819 double l0 = rayPos - sqrt(radius1*radius1 - dist2);
01820 double l1 = rayPos + sqrt(radius1*radius1 - dist2);
01821 if (l0 < 0) l0 = 0;
01822 if (l1 > rayLength) l1 = rayLength;
01823 if (l0 > l1) return 0;
01824
01825
01826
01827 c1.updateFaces();
01828 DistanceGrid::Coord p1;
01829 const SReal cubesize = c1.invDP.norm();
01830 for(int i=0;i<100;i++)
01831 {
01832 rayPos = l0 + (l1-l0)*(i*0.01);
01833 p1 = rayOrigin + rayDirection*rayPos;
01834
01835 DistanceGrid::Coord b = c1.undeform0(p1);
01836
01837 int iter;
01838 SReal err1 = 1000.0f;
01839 bool found = false;
01840 for(iter=0; iter<5; ++iter)
01841 {
01842 DistanceGrid::Coord pdeform = c1.deform(b);
01843 DistanceGrid::Coord diff = p1-pdeform;
01844 SReal err = diff.norm();
01845
01846
01847 SReal berr = err*cubesize; if (berr>0.5f) berr=0.5f;
01848 if (b[0] < -berr || b[0] > 1+berr
01849 || b[1] < -berr || b[1] > 1+berr
01850 || b[2] < -berr || b[2] > 1+berr)
01851 break;
01852 if (err < 0.001f)
01853 {
01854 if (b[0] > -0.1f && b[0] < 1.1f
01855 && b[1] > -0.1f && b[1] < 1.1f
01856 && b[2] > -0.1f && b[2] < 1.1f)
01857 {
01858 found = true;
01859 }
01860 break;
01861 }
01862 err1 = err;
01863 b += c1.undeformDir( b, diff );
01864 }
01865 if (found)
01866 {
01867 SReal d = grid1->interp(c1.initpos(b));
01868 if (d < 0)
01869 {
01870
01871 contacts->resize(contacts->size()+1);
01872 DetectionOutput *detection = &*(contacts->end()-1);
01873
01874 detection->point[0] = e2.origin() + e2.direction()*rayPos;
01875 detection->point[1] = c1.initpos(b);
01876 detection->normal = e2.direction();
01877 detection->value = d;
01878 detection->elem.first = e2;
01879 detection->elem.second = e1;
01880 detection->id = e2.getIndex();
01881 return 1;
01882 }
01883 }
01884
01885
01886
01887
01888
01889 }
01890 return 0;
01891 }
01892
01893 }
01894
01895 }
01896
01897 }
01898