00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <Box2D/Collision/b2Distance.h>
00020 #include <Box2D/Collision/Shapes/b2CircleShape.h>
00021 #include <Box2D/Collision/Shapes/b2EdgeShape.h>
00022 #include <Box2D/Collision/Shapes/b2ChainShape.h>
00023 #include <Box2D/Collision/Shapes/b2PolygonShape.h>
00024
00025
00026 int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters;
00027
00028 void b2DistanceProxy::Set(const b2Shape* shape, int32 index)
00029 {
00030 switch (shape->GetType())
00031 {
00032 case b2Shape::e_circle:
00033 {
00034 const b2CircleShape* circle = static_cast<const b2CircleShape*>(shape);
00035 m_vertices = &circle->m_p;
00036 m_count = 1;
00037 m_radius = circle->m_radius;
00038 }
00039 break;
00040
00041 case b2Shape::e_polygon:
00042 {
00043 const b2PolygonShape* polygon = static_cast<const b2PolygonShape*>(shape);
00044 m_vertices = polygon->m_vertices;
00045 m_count = polygon->m_count;
00046 m_radius = polygon->m_radius;
00047 }
00048 break;
00049
00050 case b2Shape::e_chain:
00051 {
00052 const b2ChainShape* chain = static_cast<const b2ChainShape*>(shape);
00053 b2Assert(0 <= index && index < chain->m_count);
00054
00055 m_buffer[0] = chain->m_vertices[index];
00056 if (index + 1 < chain->m_count)
00057 {
00058 m_buffer[1] = chain->m_vertices[index + 1];
00059 }
00060 else
00061 {
00062 m_buffer[1] = chain->m_vertices[0];
00063 }
00064
00065 m_vertices = m_buffer;
00066 m_count = 2;
00067 m_radius = chain->m_radius;
00068 }
00069 break;
00070
00071 case b2Shape::e_edge:
00072 {
00073 const b2EdgeShape* edge = static_cast<const b2EdgeShape*>(shape);
00074 m_vertices = &edge->m_vertex1;
00075 m_count = 2;
00076 m_radius = edge->m_radius;
00077 }
00078 break;
00079
00080 default:
00081 b2Assert(false);
00082 }
00083 }
00084
00085
00086 struct b2SimplexVertex
00087 {
00088 b2Vec2 wA;
00089 b2Vec2 wB;
00090 b2Vec2 w;
00091 float32 a;
00092 int32 indexA;
00093 int32 indexB;
00094 };
00095
00096 struct b2Simplex
00097 {
00098 void ReadCache( const b2SimplexCache* cache,
00099 const b2DistanceProxy* proxyA, const b2Transform& transformA,
00100 const b2DistanceProxy* proxyB, const b2Transform& transformB)
00101 {
00102 b2Assert(cache->count <= 3);
00103
00104
00105 m_count = cache->count;
00106 b2SimplexVertex* vertices = &m_v1;
00107 for (int32 i = 0; i < m_count; ++i)
00108 {
00109 b2SimplexVertex* v = vertices + i;
00110 v->indexA = cache->indexA[i];
00111 v->indexB = cache->indexB[i];
00112 b2Vec2 wALocal = proxyA->GetVertex(v->indexA);
00113 b2Vec2 wBLocal = proxyB->GetVertex(v->indexB);
00114 v->wA = b2Mul(transformA, wALocal);
00115 v->wB = b2Mul(transformB, wBLocal);
00116 v->w = v->wB - v->wA;
00117 v->a = 0.0f;
00118 }
00119
00120
00121
00122 if (m_count > 1)
00123 {
00124 float32 metric1 = cache->metric;
00125 float32 metric2 = GetMetric();
00126 if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon)
00127 {
00128
00129 m_count = 0;
00130 }
00131 }
00132
00133
00134 if (m_count == 0)
00135 {
00136 b2SimplexVertex* v = vertices + 0;
00137 v->indexA = 0;
00138 v->indexB = 0;
00139 b2Vec2 wALocal = proxyA->GetVertex(0);
00140 b2Vec2 wBLocal = proxyB->GetVertex(0);
00141 v->wA = b2Mul(transformA, wALocal);
00142 v->wB = b2Mul(transformB, wBLocal);
00143 v->w = v->wB - v->wA;
00144 v->a = 1.0f;
00145 m_count = 1;
00146 }
00147 }
00148
00149 void WriteCache(b2SimplexCache* cache) const
00150 {
00151 cache->metric = GetMetric();
00152 cache->count = uint16(m_count);
00153 const b2SimplexVertex* vertices = &m_v1;
00154 for (int32 i = 0; i < m_count; ++i)
00155 {
00156 cache->indexA[i] = uint8(vertices[i].indexA);
00157 cache->indexB[i] = uint8(vertices[i].indexB);
00158 }
00159 }
00160
00161 b2Vec2 GetSearchDirection() const
00162 {
00163 switch (m_count)
00164 {
00165 case 1:
00166 return -m_v1.w;
00167
00168 case 2:
00169 {
00170 b2Vec2 e12 = m_v2.w - m_v1.w;
00171 float32 sgn = b2Cross(e12, -m_v1.w);
00172 if (sgn > 0.0f)
00173 {
00174
00175 return b2Cross(1.0f, e12);
00176 }
00177 else
00178 {
00179
00180 return b2Cross(e12, 1.0f);
00181 }
00182 }
00183
00184 default:
00185 b2Assert(false);
00186 return b2Vec2_zero;
00187 }
00188 }
00189
00190 b2Vec2 GetClosestPoint() const
00191 {
00192 switch (m_count)
00193 {
00194 case 0:
00195 b2Assert(false);
00196 return b2Vec2_zero;
00197
00198 case 1:
00199 return m_v1.w;
00200
00201 case 2:
00202 return m_v1.a * m_v1.w + m_v2.a * m_v2.w;
00203
00204 case 3:
00205 return b2Vec2_zero;
00206
00207 default:
00208 b2Assert(false);
00209 return b2Vec2_zero;
00210 }
00211 }
00212
00213 void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const
00214 {
00215 switch (m_count)
00216 {
00217 case 0:
00218 b2Assert(false);
00219 break;
00220
00221 case 1:
00222 *pA = m_v1.wA;
00223 *pB = m_v1.wB;
00224 break;
00225
00226 case 2:
00227 *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA;
00228 *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB;
00229 break;
00230
00231 case 3:
00232 *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA;
00233 *pB = *pA;
00234 break;
00235
00236 default:
00237 b2Assert(false);
00238 break;
00239 }
00240 }
00241
00242 float32 GetMetric() const
00243 {
00244 switch (m_count)
00245 {
00246 case 0:
00247 b2Assert(false);
00248 return 0.0f;
00249
00250 case 1:
00251 return 0.0f;
00252
00253 case 2:
00254 return b2Distance(m_v1.w, m_v2.w);
00255
00256 case 3:
00257 return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w);
00258
00259 default:
00260 b2Assert(false);
00261 return 0.0f;
00262 }
00263 }
00264
00265 void Solve2();
00266 void Solve3();
00267
00268 b2SimplexVertex m_v1, m_v2, m_v3;
00269 int32 m_count;
00270 };
00271
00272
00273
00274
00275
00276
00277
00278
00279
00280
00281
00282
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293
00294
00295
00296 void b2Simplex::Solve2()
00297 {
00298 b2Vec2 w1 = m_v1.w;
00299 b2Vec2 w2 = m_v2.w;
00300 b2Vec2 e12 = w2 - w1;
00301
00302
00303 float32 d12_2 = -b2Dot(w1, e12);
00304 if (d12_2 <= 0.0f)
00305 {
00306
00307 m_v1.a = 1.0f;
00308 m_count = 1;
00309 return;
00310 }
00311
00312
00313 float32 d12_1 = b2Dot(w2, e12);
00314 if (d12_1 <= 0.0f)
00315 {
00316
00317 m_v2.a = 1.0f;
00318 m_count = 1;
00319 m_v1 = m_v2;
00320 return;
00321 }
00322
00323
00324 float32 inv_d12 = 1.0f / (d12_1 + d12_2);
00325 m_v1.a = d12_1 * inv_d12;
00326 m_v2.a = d12_2 * inv_d12;
00327 m_count = 2;
00328 }
00329
00330
00331
00332
00333
00334
00335 void b2Simplex::Solve3()
00336 {
00337 b2Vec2 w1 = m_v1.w;
00338 b2Vec2 w2 = m_v2.w;
00339 b2Vec2 w3 = m_v3.w;
00340
00341
00342
00343
00344
00345 b2Vec2 e12 = w2 - w1;
00346 float32 w1e12 = b2Dot(w1, e12);
00347 float32 w2e12 = b2Dot(w2, e12);
00348 float32 d12_1 = w2e12;
00349 float32 d12_2 = -w1e12;
00350
00351
00352
00353
00354
00355 b2Vec2 e13 = w3 - w1;
00356 float32 w1e13 = b2Dot(w1, e13);
00357 float32 w3e13 = b2Dot(w3, e13);
00358 float32 d13_1 = w3e13;
00359 float32 d13_2 = -w1e13;
00360
00361
00362
00363
00364
00365 b2Vec2 e23 = w3 - w2;
00366 float32 w2e23 = b2Dot(w2, e23);
00367 float32 w3e23 = b2Dot(w3, e23);
00368 float32 d23_1 = w3e23;
00369 float32 d23_2 = -w2e23;
00370
00371
00372 float32 n123 = b2Cross(e12, e13);
00373
00374 float32 d123_1 = n123 * b2Cross(w2, w3);
00375 float32 d123_2 = n123 * b2Cross(w3, w1);
00376 float32 d123_3 = n123 * b2Cross(w1, w2);
00377
00378
00379 if (d12_2 <= 0.0f && d13_2 <= 0.0f)
00380 {
00381 m_v1.a = 1.0f;
00382 m_count = 1;
00383 return;
00384 }
00385
00386
00387 if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f)
00388 {
00389 float32 inv_d12 = 1.0f / (d12_1 + d12_2);
00390 m_v1.a = d12_1 * inv_d12;
00391 m_v2.a = d12_2 * inv_d12;
00392 m_count = 2;
00393 return;
00394 }
00395
00396
00397 if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f)
00398 {
00399 float32 inv_d13 = 1.0f / (d13_1 + d13_2);
00400 m_v1.a = d13_1 * inv_d13;
00401 m_v3.a = d13_2 * inv_d13;
00402 m_count = 2;
00403 m_v2 = m_v3;
00404 return;
00405 }
00406
00407
00408 if (d12_1 <= 0.0f && d23_2 <= 0.0f)
00409 {
00410 m_v2.a = 1.0f;
00411 m_count = 1;
00412 m_v1 = m_v2;
00413 return;
00414 }
00415
00416
00417 if (d13_1 <= 0.0f && d23_1 <= 0.0f)
00418 {
00419 m_v3.a = 1.0f;
00420 m_count = 1;
00421 m_v1 = m_v3;
00422 return;
00423 }
00424
00425
00426 if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f)
00427 {
00428 float32 inv_d23 = 1.0f / (d23_1 + d23_2);
00429 m_v2.a = d23_1 * inv_d23;
00430 m_v3.a = d23_2 * inv_d23;
00431 m_count = 2;
00432 m_v1 = m_v3;
00433 return;
00434 }
00435
00436
00437 float32 inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3);
00438 m_v1.a = d123_1 * inv_d123;
00439 m_v2.a = d123_2 * inv_d123;
00440 m_v3.a = d123_3 * inv_d123;
00441 m_count = 3;
00442 }
00443
00444 void b2Distance(b2DistanceOutput* output,
00445 b2SimplexCache* cache,
00446 const b2DistanceInput* input)
00447 {
00448 ++b2_gjkCalls;
00449
00450 const b2DistanceProxy* proxyA = &input->proxyA;
00451 const b2DistanceProxy* proxyB = &input->proxyB;
00452
00453 b2Transform transformA = input->transformA;
00454 b2Transform transformB = input->transformB;
00455
00456
00457 b2Simplex simplex;
00458 simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB);
00459
00460
00461 b2SimplexVertex* vertices = &simplex.m_v1;
00462 const int32 k_maxIters = 20;
00463
00464
00465
00466 int32 saveA[3], saveB[3];
00467 int32 saveCount = 0;
00468
00469 float32 distanceSqr1 = b2_maxFloat;
00470 float32 distanceSqr2 = distanceSqr1;
00471
00472
00473 int32 iter = 0;
00474 while (iter < k_maxIters)
00475 {
00476
00477 saveCount = simplex.m_count;
00478 for (int32 i = 0; i < saveCount; ++i)
00479 {
00480 saveA[i] = vertices[i].indexA;
00481 saveB[i] = vertices[i].indexB;
00482 }
00483
00484 switch (simplex.m_count)
00485 {
00486 case 1:
00487 break;
00488
00489 case 2:
00490 simplex.Solve2();
00491 break;
00492
00493 case 3:
00494 simplex.Solve3();
00495 break;
00496
00497 default:
00498 b2Assert(false);
00499 }
00500
00501
00502 if (simplex.m_count == 3)
00503 {
00504 break;
00505 }
00506
00507
00508 b2Vec2 p = simplex.GetClosestPoint();
00509 distanceSqr2 = p.LengthSquared();
00510
00511
00512 if (distanceSqr2 >= distanceSqr1)
00513 {
00514
00515 }
00516 distanceSqr1 = distanceSqr2;
00517
00518
00519 b2Vec2 d = simplex.GetSearchDirection();
00520
00521
00522 if (d.LengthSquared() < b2_epsilon * b2_epsilon)
00523 {
00524
00525
00526
00527
00528
00529
00530 break;
00531 }
00532
00533
00534 b2SimplexVertex* vertex = vertices + simplex.m_count;
00535 vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d));
00536 vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA));
00537 b2Vec2 wBLocal;
00538 vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d));
00539 vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB));
00540 vertex->w = vertex->wB - vertex->wA;
00541
00542
00543 ++iter;
00544 ++b2_gjkIters;
00545
00546
00547 bool duplicate = false;
00548 for (int32 i = 0; i < saveCount; ++i)
00549 {
00550 if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i])
00551 {
00552 duplicate = true;
00553 break;
00554 }
00555 }
00556
00557
00558 if (duplicate)
00559 {
00560 break;
00561 }
00562
00563
00564 ++simplex.m_count;
00565 }
00566
00567 b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter);
00568
00569
00570 simplex.GetWitnessPoints(&output->pointA, &output->pointB);
00571 output->distance = b2Distance(output->pointA, output->pointB);
00572 output->iterations = iter;
00573
00574
00575 simplex.WriteCache(cache);
00576
00577
00578 if (input->useRadii)
00579 {
00580 float32 rA = proxyA->m_radius;
00581 float32 rB = proxyB->m_radius;
00582
00583 if (output->distance > rA + rB && output->distance > b2_epsilon)
00584 {
00585
00586
00587 output->distance -= rA + rB;
00588 b2Vec2 normal = output->pointB - output->pointA;
00589 normal.Normalize();
00590 output->pointA += rA * normal;
00591 output->pointB -= rB * normal;
00592 }
00593 else
00594 {
00595
00596
00597 b2Vec2 p = 0.5f * (output->pointA + output->pointB);
00598 output->pointA = p;
00599 output->pointB = p;
00600 output->distance = 0.0f;
00601 }
00602 }
00603 }