step/stepcore
collisionsolver.cc
Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include "collisionsolver.h"
00020 #include "rigidbody.h"
00021 #include "particle.h"
00022
00023 #include <algorithm>
00024
00025 namespace StepCore {
00026
00027
00028 STEPCORE_META_OBJECT(CollisionSolver, "CollisionSolver", MetaObject::ABSTRACT, STEPCORE_SUPER_CLASS(Object),
00029 STEPCORE_PROPERTY_RW(double, toleranceAbs, STEPCORE_UNITS_1, "Allowed absolute tolerance", toleranceAbs, setToleranceAbs)
00030 STEPCORE_PROPERTY_R_D(double, localError, STEPCORE_UNITS_1, "Maximal local error during last step", localError))
00031
00032 STEPCORE_META_OBJECT(GJKCollisionSolver, "GJKCollisionSolver", 0,
00033 STEPCORE_SUPER_CLASS(CollisionSolver),)
00034
00035 int GJKCollisionSolver::checkPolygonPolygon(Contact* contact)
00036 {
00037 BasePolygon* polygon0 = static_cast<BasePolygon*>(contact->body0);
00038 BasePolygon* polygon1 = static_cast<BasePolygon*>(contact->body1);
00039
00040 if(polygon0->vertexes().empty() || polygon1->vertexes().empty()) {
00041 return contact->state = Contact::Unknown;
00042 }
00043
00044
00045
00046
00047
00048
00049 Vector2dList vertexes[2];
00050 vertexes[0].reserve(polygon0->vertexes().size());
00051 vertexes[1].reserve(polygon1->vertexes().size());
00052
00053 const Vector2dList::const_iterator p0_it_end = polygon0->vertexes().end();
00054 for(Vector2dList::const_iterator it0 = polygon0->vertexes().begin();
00055 it0 != p0_it_end; ++it0) {
00056 vertexes[0].push_back(polygon0->pointLocalToWorld(*it0));
00057 }
00058
00059 const Vector2dList::const_iterator p1_it_end = polygon1->vertexes().end();
00060 for(Vector2dList::const_iterator it1 = polygon1->vertexes().begin();
00061 it1 != p1_it_end; ++it1) {
00062 vertexes[1].push_back(polygon1->pointLocalToWorld(*it1));
00063 }
00064
00065 int wsize;
00066 Vector2d w[3];
00067 Vector2d v;
00068 Vector2d s;
00069
00070 Vector2d vv[2];
00071 int wi[2][3];
00072 int si[2];
00073
00074 wsize = 1;
00075
00076 if(contact->state >= Contact::Separating && contact->state < Contact::Intersected) {
00077 wi[0][0] = contact->_w1[0];
00078 wi[1][0] = contact->_w1[1];
00079 } else {
00080 wi[0][0] = 0;
00081 wi[1][0] = 0;
00082 }
00083 vv[0] = vertexes[0][wi[0][0]];
00084 vv[1] = vertexes[1][wi[1][0]];
00085 w[0] = v = vv[1] - vv[0];
00086
00087 bool intersects = false;
00088 unsigned int iteration = 0;
00089 for(;; ++iteration) {
00090
00091
00092 double smin = v.norm2();
00093
00094
00095
00096
00097 if(smin < _toleranceAbs*_toleranceAbs*1e-4) {
00098 intersects = true;
00099 break;
00100 }
00101
00102
00103
00104 bool sfound = false;
00105 unsigned int vertex0_size = vertexes[0].size();
00106 unsigned int vertex1_size = vertexes[1].size();
00107
00108 for(unsigned int i0=0; i0<vertex0_size; ++i0) {
00109 for(unsigned int i1=0; i1<vertex1_size; ++i1) {
00110 Vector2d sn = vertexes[1][i1] - vertexes[0][i0];
00111 double scurr = v.innerProduct(sn);
00112 if(smin - scurr > _toleranceAbs*_toleranceAbs*1e-4) {
00113 smin = scurr;
00114 s = sn;
00115 si[0] = i0;
00116 si[1] = i1;
00117 sfound = true;
00118 }
00119 }
00120 }
00121
00122
00123 if(!sfound) {
00124 if(wsize == 0) {
00125 w[0] = v;
00126 wi[0][0] = 0;
00127 wi[1][0] = 0;
00128 wsize = 1;
00129 }
00130 break;
00131 }
00132
00133
00134 if(wsize == 2) {
00135
00136
00137 Vector2d w02 = w[0] - s;
00138 Vector2d w12 = w[1] - s;
00139 double det = w02[0]*w12[1] - w02[1]*w12[0];
00140 double det0 = -s[0]*w12[1] + s[1]*w12[0];
00141 double det1 = -w02[0]* s[1] + w02[1]* s[0];
00142 if(det0/det > 0 && det1/det > 0) {
00143 w[wsize] = s;
00144 wi[0][wsize] = si[0];
00145 wi[1][wsize] = si[1];
00146 ++wsize;
00147 v.setZero();
00148 intersects = true;
00149 break;
00150 }
00151 }
00152
00153
00154 double lambda = 0;
00155 int ii = -1;
00156 for(int i=0; i<wsize; ++i) {
00157 double lambda0 = - s.innerProduct(w[i]-s) / (w[i]-s).norm2();
00158 if(lambda0 > 0) {
00159 Vector2d vn = s*(1-lambda0) + w[i]*lambda0;
00160 if(vn.norm2() < v.norm2()) {
00161 v = vn; ii = i;
00162 lambda = lambda0;
00163 }
00164 }
00165 }
00166
00167 if(ii >= 0) {
00168 vv[0] = vertexes[0][si[0]]*(1-lambda) + vertexes[0][wi[0][ii]]*lambda;
00169 vv[1] = vertexes[1][si[1]]*(1-lambda) + vertexes[1][wi[1][ii]]*lambda;
00170 if(wsize == 2) {
00171 w[1-ii] = s;
00172 wi[0][1-ii] = si[0];
00173 wi[1][1-ii] = si[1];
00174 } else {
00175 w[wsize] = s;
00176 wi[0][wsize] = si[0];
00177 wi[1][wsize] = si[1];
00178 ++wsize;
00179 }
00180 } else {
00181 STEPCORE_ASSERT_NOABORT(iteration == 0 || s.norm2() < v.norm2());
00182
00183 v = w[0] = s;
00184 vv[0] = vertexes[0][si[0]];
00185 vv[1] = vertexes[1][si[1]];
00186 wi[0][0] = si[0];
00187 wi[1][0] = si[1];
00188 wsize = 1;
00189 }
00190 }
00191
00192 if(intersects) {
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202 contact->distance = 0;
00203 contact->normal.setZero();
00204 contact->pointsCount = 0;
00205 return contact->state = Contact::Intersected;
00206 }
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222 double vnorm = v.norm();
00223 contact->distance = vnorm;
00224 contact->normal = v/vnorm;
00225 contact->pointsCount = 0;
00226 contact->state = Contact::Separated;
00227
00228 contact->_w1[0] = wi[0][0];
00229 contact->_w1[1] = wi[1][0];
00230
00231 if(vnorm > _toleranceAbs) return contact->state;
00232
00233
00234
00235
00236
00237
00238 Vector2d vunit = v / vnorm;
00239 Vector2d wm[2][2];
00240
00241 for(int i=0; i<2; ++i) {
00242 wm[i][0] = vertexes[i][ wi[i][0] ];
00243
00244 if(wsize < 2 || wi[i][0] == wi[i][1]) {
00245
00246 int ai1 = wi[i][0] - 1; if(ai1 < 0) ai1 = vertexes[i].size()-1;
00247 Vector2d av1 = vertexes[i][ai1];
00248 Vector2d dv1 = wm[i][0] - av1;
00249 double dist1 = vunit.innerProduct( dv1 ) * (i==0 ? 1 : -1);
00250 double angle1 = dist1 / dv1.norm();
00251
00252 int ai2 = wi[i][0] + 1; if(ai2 >= (int) vertexes[i].size()) ai2 = 0;
00253 Vector2d av2 = vertexes[i][ai2];
00254 Vector2d dv2 = wm[i][0] - av2;
00255 double dist2 = vunit.innerProduct( dv2 ) * (i==0 ? 1 : -1);
00256 double angle2 = dist2 / dv2.norm();
00257
00258 if(angle1 <= angle2 && dist1 < (_toleranceAbs-vnorm)/2) {
00259 wm[i][1] = av1;
00260 } else if(angle2 <= angle1 && dist2 < (_toleranceAbs-vnorm)/2) {
00261 wm[i][1] = av2;
00262 } else {
00263 wm[i][1] = wm[i][0]; contact->pointsCount = 1;
00264 break;
00265 }
00266 } else {
00267 wm[i][1] = vertexes[i][ wi[i][1] ];
00268 }
00269 }
00270
00271
00272 if(contact->pointsCount != 1) {
00273 Vector2d vunit_o(-vunit[1], vunit[0]);
00274 double wm_o[2][2];
00275
00276 for(int i=0; i<2; ++i) {
00277 wm_o[i][0] = vunit_o.innerProduct(wm[i][0]);
00278 wm_o[i][1] = vunit_o.innerProduct(wm[i][1]);
00279
00280 if(wm_o[i][0] > wm_o[i][1]) {
00281 std::swap(wm_o[i][0], wm_o[i][1]);
00282 std::swap(wm[i][0], wm[i][1]);
00283 }
00284 }
00285
00286 if(wm_o[0][0] > wm_o[1][0]) contact->points[0] = wm[0][0];
00287 else contact->points[0] = wm[1][0];
00288
00289 if(wm_o[0][1] < wm_o[1][1]) contact->points[1] = wm[0][1];
00290 else contact->points[1] = wm[1][1];
00291
00292
00293 if((contact->points[1] - contact->points[0]).norm() > _toleranceAbs) {
00294
00295
00296
00297
00298
00299 contact->pointsCount = 2;
00300 }
00301
00302
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 }
00316
00317 if(contact->pointsCount != 2) {
00318 contact->pointsCount = 1;
00319 contact->points[0] = vv[0];
00320
00321 }
00322
00323 int pCount = contact->pointsCount;
00324 for(int i=0; i<pCount; ++i) {
00325 contact->vrel[i] = contact->normal.innerProduct(
00326 polygon1->velocityWorld(contact->points[i]) -
00327 polygon0->velocityWorld(contact->points[i]));
00328
00329 if(contact->vrel[i] < 0)
00330 contact->pointsState[i] = Contact::Colliding;
00331 else if(contact->vrel[i] < _toleranceAbs)
00332 contact->pointsState[i] = Contact::Contacted;
00333 else contact->pointsState[i] = Contact::Separating;
00334
00335 if(contact->pointsState[i] > contact->state)
00336 contact->state = contact->pointsState[i];
00337 }
00338
00339 contact->normalDerivative.setZero();
00340 return contact->state;
00341 }
00342
00343 int GJKCollisionSolver::checkPolygonDisk(Contact* contact)
00344 {
00345 BasePolygon* polygon0 = static_cast<BasePolygon*>(contact->body0);
00346 Disk* disk1 = static_cast<Disk*>(contact->body1);
00347
00348 if(polygon0->vertexes().empty()) {
00349 return contact->state = Contact::Unknown;
00350 }
00351
00352
00353
00354 Vector2dList vertexes;
00355 vertexes.reserve(polygon0->vertexes().size());
00356
00357 const Vector2dList::const_iterator p0_it_end = polygon0->vertexes().end();
00358 for(Vector2dList::const_iterator it0 = polygon0->vertexes().begin();
00359 it0 != p0_it_end; ++it0) {
00360 vertexes.push_back(polygon0->pointLocalToWorld(*it0));
00361 }
00362
00363 int wsize;
00364 Vector2d w[3];
00365 Vector2d v;
00366 Vector2d s;
00367
00368 Vector2d vv;
00369 int wi[3];
00370 int si;
00371
00372
00373 wsize = 1;
00374 if(contact->state >= Contact::Separating && contact->state < Contact::Intersected) {
00375 wi[0] = contact->_w1[0];
00376 } else {
00377 wi[0] = 0;
00378 }
00379 vv = vertexes[wi[0]];
00380 w[0] = v = disk1->position() - vv;
00381
00382 bool intersects = false;
00383 unsigned int iteration = 0;
00384 for(;; ++iteration) {
00385
00386
00387 double smin = v.norm2();
00388
00389
00390
00391
00392 if(std::sqrt(smin) - disk1->radius() < _toleranceAbs*1e-2) {
00393 intersects = true;
00394 break;
00395 }
00396
00397
00398
00399 bool sfound = false;
00400 unsigned int vertex_size = vertexes.size();
00401
00402 for(unsigned int i0=0; i0<vertex_size; ++i0) {
00403 Vector2d sn = disk1->position() - vertexes[i0];
00404 double scurr = v.innerProduct(sn);
00405 if(smin - scurr > _toleranceAbs*_toleranceAbs*1e-4) {
00406 smin = scurr;
00407 s = sn;
00408 si = i0;
00409 sfound = true;
00410 }
00411 }
00412
00413
00414 if(!sfound) {
00415 if(wsize == 0) {
00416 w[0] = v;
00417 wi[0] = 0;
00418 wsize = 1;
00419 }
00420 break;
00421 }
00422
00423
00424 if(wsize == 2) {
00425
00426
00427 Vector2d w02 = w[0] - s;
00428 Vector2d w12 = w[1] - s;
00429 Vector2d s0 = s - s.unit() * disk1->radius();
00430 double det = w02[0]*w12[1] - w02[1]*w12[0];
00431 double det0 = -s0[0]*w12[1] + s0[1]*w12[0];
00432 double det1 = -w02[0]* s0[1] + w02[1]* s0[0];
00433 if(det0/det > 0 && det1/det > 0) {
00434 w[wsize] = s;
00435 wi[wsize] = si;
00436 ++wsize;
00437 v.setZero();
00438 intersects = true;
00439 break;
00440 }
00441 }
00442
00443
00444 double lambda = 0;
00445 int ii = -1;
00446 for(int i=0; i<wsize; ++i) {
00447 double lambda0 = - s.innerProduct(w[i]-s) / (w[i]-s).norm2();
00448 if(lambda0 > 0) {
00449 Vector2d vn = s*(1-lambda0) + w[i]*lambda0;
00450 if(vn.norm2() < v.norm2()) {
00451 v = vn; ii = i;
00452 lambda = lambda0;
00453 }
00454 }
00455 }
00456
00457 if(ii >= 0) {
00458 vv = vertexes[si]*(1-lambda) + vertexes[wi[ii]]*lambda;
00459 if(wsize == 2) {
00460 w[1-ii] = s;
00461 wi[1-ii] = si;
00462 } else {
00463 w[wsize] = s;
00464 wi[wsize] = si;
00465 ++wsize;
00466 }
00467 } else {
00468 STEPCORE_ASSERT_NOABORT(iteration == 0 || s.norm2() < v.norm2());
00469
00470 v = w[0] = s;
00471 vv = vertexes[si];
00472 wi[0] = si;
00473 wsize = 1;
00474 }
00475 }
00476
00477 if(intersects) {
00478
00479
00480
00481
00482
00483
00484
00485 contact->distance = 0;
00486 contact->normal.setZero();
00487 contact->pointsCount = 0;
00488 return contact->state = Contact::Intersected;
00489 }
00490
00491
00492
00493
00494
00495
00496
00497
00498
00499
00500
00501
00502
00503
00504
00505 double vnorm = v.norm();
00506 contact->distance = vnorm - disk1->radius();
00507 contact->normal = v/vnorm;
00508
00509 contact->_w1[0] = wi[0];
00510
00511 if(contact->distance > _toleranceAbs) {
00512 contact->pointsCount = 0;
00513 contact->state = Contact::Separated;
00514 return contact->state;
00515 }
00516
00517
00518
00519
00520 contact->pointsCount = 1;
00521 contact->points[0] = disk1->position() - contact->normal * disk1->radius();
00522 contact->vrel[0] = contact->normal.innerProduct(
00523 disk1->velocity() -
00524 polygon0->velocityWorld(contact->points[0]));
00525
00526 if(contact->vrel[0] < 0)
00527 contact->pointsState[0] = Contact::Colliding;
00528 else if(contact->vrel[0] < _toleranceAbs)
00529 contact->pointsState[0] = Contact::Contacted;
00530 else contact->pointsState[0] = Contact::Separating;
00531
00532 contact->normalDerivative.setZero();
00533 contact->state = contact->pointsState[0];
00534 return contact->state;
00535 }
00536
00537 int GJKCollisionSolver::checkPolygonParticle(Contact* contact)
00538 {
00539 BasePolygon* polygon0 = static_cast<BasePolygon*>(contact->body0);
00540 Particle* particle1 = static_cast<Particle*>(contact->body1);
00541
00542 if(polygon0->vertexes().empty()) {
00543 return contact->state = Contact::Unknown;
00544 }
00545
00546
00547
00548 Vector2dList vertexes;
00549 vertexes.reserve(polygon0->vertexes().size());
00550
00551 const Vector2dList::const_iterator p0_it_end = polygon0->vertexes().end();
00552 for(Vector2dList::const_iterator it0 = polygon0->vertexes().begin();
00553 it0 != p0_it_end; ++it0) {
00554 vertexes.push_back(polygon0->pointLocalToWorld(*it0));
00555 }
00556
00557 int wsize;
00558 Vector2d w[3];
00559 Vector2d v;
00560 Vector2d s;
00561
00562 Vector2d vv;
00563 int wi[3];
00564 int si;
00565
00566
00567 wsize = 1;
00568 if(contact->state >= Contact::Separating && contact->state < Contact::Intersected) {
00569 wi[0] = contact->_w1[0];
00570 } else {
00571 wi[0] = 0;
00572 }
00573 vv = vertexes[wi[0]];
00574 w[0] = v = particle1->position() - vv;
00575
00576 bool intersects = false;
00577 unsigned int iteration = 0;
00578 for(;; ++iteration) {
00579
00580
00581 double smin = v.norm2();
00582
00583
00584
00585
00586 if(smin < _toleranceAbs*_toleranceAbs*1e-4) {
00587 intersects = true;
00588 break;
00589 }
00590
00591
00592
00593 bool sfound = false;
00594 unsigned int vertex_size = vertexes.size();
00595
00596 for(unsigned int i0=0; i0<vertex_size; ++i0) {
00597 Vector2d sn = particle1->position() - vertexes[i0];
00598 double scurr = v.innerProduct(sn);
00599 if(smin - scurr > _toleranceAbs*_toleranceAbs*1e-4) {
00600 smin = scurr;
00601 s = sn;
00602 si = i0;
00603 sfound = true;
00604 }
00605 }
00606
00607
00608 if(!sfound) {
00609 if(wsize == 0) {
00610 w[0] = v;
00611 wi[0] = 0;
00612 wsize = 1;
00613 }
00614 break;
00615 }
00616
00617
00618 if(wsize == 2) {
00619
00620
00621 Vector2d w02 = w[0] - s;
00622 Vector2d w12 = w[1] - s;
00623 double det = w02[0]*w12[1] - w02[1]*w12[0];
00624 double det0 = -s[0]*w12[1] + s[1]*w12[0];
00625 double det1 = -w02[0]* s[1] + w02[1]* s[0];
00626 if(det0/det > 0 && det1/det > 0) {
00627 w[wsize] = s;
00628 wi[wsize] = si;
00629 ++wsize;
00630 v.setZero();
00631 intersects = true;
00632 break;
00633 }
00634 }
00635
00636
00637 double lambda = 0;
00638 int ii = -1;
00639 for(int i=0; i<wsize; ++i) {
00640 double lambda0 = - s.innerProduct(w[i]-s) / (w[i]-s).norm2();
00641 if(lambda0 > 0) {
00642 Vector2d vn = s*(1-lambda0) + w[i]*lambda0;
00643 if(vn.norm2() < v.norm2()) {
00644 v = vn; ii = i;
00645 lambda = lambda0;
00646 }
00647 }
00648 }
00649
00650 if(ii >= 0) {
00651 vv = vertexes[si]*(1-lambda) + vertexes[wi[ii]]*lambda;
00652 if(wsize == 2) {
00653 w[1-ii] = s;
00654 wi[1-ii] = si;
00655 } else {
00656 w[wsize] = s;
00657 wi[wsize] = si;
00658 ++wsize;
00659 }
00660 } else {
00661 STEPCORE_ASSERT_NOABORT(iteration == 0 || s.norm2() < v.norm2());
00662
00663 v = w[0] = s;
00664 vv = vertexes[si];
00665 wi[0] = si;
00666 wsize = 1;
00667 }
00668 }
00669
00670 if(intersects) {
00671
00672
00673
00674
00675
00676
00677
00678
00679
00680 contact->distance = 0;
00681 contact->normal.setZero();
00682 contact->pointsCount = 0;
00683 return contact->state = Contact::Intersected;
00684 }
00685
00686
00687
00688
00689
00690
00691
00692
00693
00694
00695
00696
00697
00698
00699
00700 double vnorm = v.norm();
00701 contact->distance = vnorm;
00702 contact->normal = v/vnorm;
00703
00704 contact->_w1[0] = wi[0];
00705
00706 if(vnorm > _toleranceAbs) {
00707 contact->pointsCount = 0;
00708 contact->state = Contact::Separated;
00709 return contact->state;
00710 }
00711
00712 contact->pointsCount = 1;
00713 contact->points[0] = particle1->position();
00714 contact->vrel[0] = contact->normal.innerProduct(
00715 particle1->velocity() -
00716 polygon0->velocityWorld(contact->points[0]));
00717
00718 if(contact->vrel[0] < 0)
00719 contact->pointsState[0] = Contact::Colliding;
00720 else if(contact->vrel[0] < _toleranceAbs)
00721 contact->pointsState[0] = Contact::Contacted;
00722 else contact->pointsState[0] = Contact::Separating;
00723
00724 contact->state = contact->pointsState[0];
00725 return contact->state;
00726 }
00727
00728 int GJKCollisionSolver::checkDiskDisk(Contact* contact)
00729 {
00730 Disk* disk0 = static_cast<Disk*>(contact->body0);
00731 Disk* disk1 = static_cast<Disk*>(contact->body1);
00732
00733 Vector2d r = disk1->position() - disk0->position();
00734 double rd = disk1->radius() + disk0->radius();
00735 double rn = r.norm();
00736 contact->normal = r/rn;
00737 contact->distance = rn - rd;
00738
00739 if(contact->distance > _toleranceAbs) {
00740 contact->state = Contact::Separated;
00741 return contact->state;
00742 } else if(contact->distance < 0) {
00743 contact->state = Contact::Intersected;
00744 return contact->state;
00745 }
00746
00747 contact->pointsCount = 1;
00748 contact->points[0] = disk0->position() + contact->normal * disk0->radius();
00749
00750 Vector2d v = disk1->velocity() - disk0->velocity();
00751 contact->vrel[0] = contact->normal.innerProduct(v);
00752 contact->normalDerivative = v / rn - (r.innerProduct(v)/rn/rn/rn) * r;
00753
00754 if(contact->vrel[0] < 0)
00755 contact->pointsState[0] = Contact::Colliding;
00756 else if(contact->vrel[0] < _toleranceAbs)
00757 contact->pointsState[0] = Contact::Contacted;
00758 else contact->pointsState[0] = Contact::Separating;
00759
00760 contact->normalDerivative.setZero();
00761 contact->state = contact->pointsState[0];
00762 return contact->state;
00763 }
00764
00765 int GJKCollisionSolver::checkDiskParticle(Contact* contact)
00766 {
00767 Disk* disk0 = static_cast<Disk*>(contact->body0);
00768 Particle* particle1 = static_cast<Particle*>(contact->body1);
00769
00770 Vector2d r = particle1->position() - disk0->position();
00771 double rd = disk0->radius();
00772 double rn = r.norm();
00773 contact->normal = r/rn;
00774 contact->distance = rn - rd;
00775
00776 if(contact->distance > _toleranceAbs) {
00777 contact->state = Contact::Separated;
00778 return contact->state;
00779 } else if(contact->distance < _toleranceAbs*1e-2) {
00780 contact->state = Contact::Intersected;
00781 return contact->state;
00782 }
00783
00784 contact->pointsCount = 1;
00785 contact->points[0] = disk0->position() + contact->normal * disk0->radius();
00786
00787 Vector2d v = particle1->velocity() - disk0->velocity();
00788 contact->vrel[0] = contact->normal.innerProduct(v);
00789 contact->normalDerivative = v / rn - (r.innerProduct(v)/rn/rn/rn) * r;
00790
00791 if(contact->vrel[0] < 0)
00792 contact->pointsState[0] = Contact::Colliding;
00793 else if(contact->vrel[0] < _toleranceAbs)
00794 contact->pointsState[0] = Contact::Contacted;
00795 else contact->pointsState[0] = Contact::Separating;
00796
00797 contact->state = contact->pointsState[0];
00798 return contact->state;
00799 }
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824 inline int GJKCollisionSolver::checkContact(Contact* contact)
00825 {
00826 if(contact->type == Contact::PolygonPolygonType) checkPolygonPolygon(contact);
00827 else if(contact->type == Contact::PolygonDiskType) checkPolygonDisk(contact);
00828 else if(contact->type == Contact::PolygonParticleType) checkPolygonParticle(contact);
00829 else if(contact->type == Contact::DiskDiskType) checkDiskDisk(contact);
00830 else if(contact->type == Contact::DiskParticleType) checkDiskParticle(contact);
00831 else contact->state = Contact::Unknown;
00832 return contact->state;
00833 }
00834
00835 int GJKCollisionSolver::checkContacts(BodyList& bodies, ConstraintsInfo* info, bool collisions)
00836 {
00837 int state = Contact::Unknown;
00838
00839 checkCache(bodies);
00840
00841
00842 const ContactValueList::iterator end = _contacts.end();
00843 for(ContactValueList::iterator it = _contacts.begin(); it != end; ++it) {
00844 Contact& contact = *it;
00845
00846 checkContact(&contact);
00847
00848 if(contact.state > state) state = contact.state;
00849 if(contact.state == Contact::Intersected) return state;
00850 }
00851
00852 if(info) {
00853
00854 for(ContactValueList::iterator it = _contacts.begin(); it != end; ++it) {
00855 Contact& contact = *it;
00856 if(contact.state == Contact::Contacted) {
00857
00858 for(int p=0; p<contact.pointsCount; ++p) {
00859 int i = info->addContact();
00860
00861
00862
00863
00864
00865
00866
00867
00868
00869 info->jacobian.row(i).w(contact.body0->variablesOffset() +
00870 RigidBody::PositionOffset, -contact.normal[0]);
00871 info->jacobian.row(i).w(contact.body0->variablesOffset() +
00872 RigidBody::PositionOffset+1, -contact.normal[1]);
00873 info->jacobian.row(i).w(contact.body1->variablesOffset() +
00874 RigidBody::PositionOffset, contact.normal[0]);
00875 info->jacobian.row(i).w(contact.body1->variablesOffset() +
00876 RigidBody::PositionOffset+1, contact.normal[1]);
00877
00878 if(!collisions) {
00879 info->jacobianDerivative.row(i).w(contact.body0->variablesOffset() +
00880 RigidBody::PositionOffset, -contact.normalDerivative[0]);
00881 info->jacobianDerivative.row(i).w(contact.body0->variablesOffset() +
00882