Flatland

Documentation

SourceForge.net Logo

quad-quad.cpp

Go to the documentation of this file.
00001 // Summary: Test for quad-quad intersection and generate contacts.
00002 // Copyright: 2007  Philip Rideout.  All rights reserved.
00003 // License: see bsd-license.txt
00004 
00005 #include <flatland/shapes.hpp>
00006 #include <flatland/intersection.hpp>
00007 
00008 // define an anonymous namespace as a place for storing off
00009 // computed information shared by Test and Find
00010 namespace
00011 {
00012     Flatland::vec2 delta;
00013     float dotA0B0, dotA0B1, dotA1B0, dotA1B1;
00014     float absDotA0B0, absDotA0B1, absDotA1B0, absDotA1B1;
00015     float extAA0B0, extAA0B1, extAA1B0, extAA1B1, extBA0B0, extBA0B1, extBA1B0, extBA1B1;
00016     float depth;
00017     enum ECode {NA0, NA1, NB0, NB1, PA0, PA1, PB0, PB1} code;
00018 }
00019 
00020 bool Flatland::Intersection::TestQuadQuad(const Geometry &g1, const Geometry &g2)
00021 {
00022     assert(g1.GetShape() == Shape::Quad);
00023     assert(g2.GetShape() == Shape::Quad);
00024     const Quad &a = static_cast<const Quad&>(g1);
00025     const Quad &b = static_cast<const Quad&>(g2);
00026 
00027     delta = a.Center() - b.Center();
00028     float minDepth = HUGE_VAL;
00029 
00030     // test the seperating axis of a.Axis(0)
00031     dotA0B0 = dot(a.Axis(0), b.Axis(0));
00032     absDotA0B0 = fabsf(dotA0B0);
00033     dotA0B1 = dot(a.Axis(0), b.Axis(1));
00034     absDotA0B1 = fabsf(dotA0B1);
00035     extBA0B0 = b.Extent(0)*absDotA0B0;
00036     extBA0B1 = b.Extent(1)*absDotA0B1;
00037     float dist1 = dot(a.Axis(0), delta);
00038     float dist2 = a.Extent(0) + extBA0B0 + extBA0B1;
00039     depth = dist2 - fabsf(dist1);
00040     if (depth < 0)
00041         return false;
00042     if (depth < minDepth)
00043     {
00044         minDepth = depth;
00045         code = dist1 < 0 ? NA0 : PA0;
00046     }
00047 
00048     // test the seperating axis of a.Axis(1)
00049     dotA1B0 = dot(a.Axis(1), b.Axis(0));
00050     absDotA1B0 = fabsf(dotA1B0);
00051     dotA1B1 = dot(a.Axis(1), b.Axis(1));
00052     absDotA1B1 = fabsf(dotA1B1);
00053     extBA1B0 = b.Extent(0)*absDotA1B0;
00054     extBA1B1 = b.Extent(1)*absDotA1B1;
00055     dist1 = dot(a.Axis(1), delta);
00056     dist2 = a.Extent(1) + extBA1B0 + extBA1B1;
00057     depth = dist2 - fabsf(dist1);
00058     if (depth < 0)
00059         return false;
00060     if (depth < minDepth)
00061     {
00062         minDepth = depth;
00063         code = dist1 < 0 ? NA1 : PA1;
00064     }
00065 
00066     // test the seperating axis of b.Axis(0)
00067     extAA0B0 = a.Extent(0)*absDotA0B0;
00068     extAA1B0 = a.Extent(1)*absDotA1B0;
00069     dist1 = dot(b.Axis(0), delta);
00070     dist2 = b.Extent(0) + extAA0B0 + extAA1B0;
00071     depth = dist2 - fabsf(dist1);
00072     if (depth < 0)
00073         return false;
00074     if (depth < minDepth)
00075     {
00076         minDepth = depth;
00077         code = dist1 < 0 ? NB0 : PB0;
00078     }
00079 
00080     // test the seperating axis of b.Axis(1)
00081     extAA0B1 = a.Extent(0)*absDotA0B1;
00082     extAA1B1 = a.Extent(1)*absDotA1B1;
00083     dist1 = dot(b.Axis(1), delta);
00084     dist2 = b.Extent(1) + extAA0B1 + extAA1B1;
00085     depth = dist2 - fabsf(dist1);
00086     if (depth < 0)
00087         return false;
00088     if (depth < minDepth)
00089     {
00090         minDepth = depth;
00091         code = dist1 < 0 ? NB1 : PB1;
00092     }
00093 
00094     return true;
00095 }
00096 
00097 void Flatland::Intersection::FindQuadQuad(const Geometry &g1, const Geometry &g2, ContactList &contacts)
00098 {
00099     assert(g1.GetShape() == Shape::Quad);
00100     assert(g2.GetShape() == Shape::Quad);
00101     const Quad &a = static_cast<const Quad&>(g1);
00102     const Quad &b = static_cast<const Quad&>(g2);
00103 
00104     vec2 normal;
00105     vec2 normal2;
00106     vec2 center;
00107     int axis0, axis1;
00108     int a0, a1;
00109     const Quad *reference;
00110     const Quad *incident;
00111     float m11;
00112     float k1;
00113     bool negate;
00114 
00115     switch (code)
00116     {
00117         case PA0:
00118             normal = a.Axis(0);
00119             axis0 = 0; axis1 = 1;
00120             normal2 = -normal;
00121             reference = &a; incident = &b;
00122             a0 = absDotA0B1 > absDotA0B0 ? 1 : 0; a1 = 1 - a0;
00123             if (a1)
00124             {
00125                 m11 = dotA1B1;
00126                 k1 = extBA1B1;
00127                 negate = -dotA0B0 < 0;
00128             }
00129             else
00130             {
00131                 m11 = dotA1B0;
00132                 k1 = extBA1B0;
00133                 negate = -dotA0B1 < 0;
00134             }
00135             center = -delta;
00136             break;
00137 
00138         case PA1:
00139             normal = a.Axis(1);
00140             axis0 = 1; axis1 = 0;
00141             normal2 = -normal;
00142             reference = &a; incident = &b;
00143             a0 = absDotA1B1 > absDotA1B0 ? 1 : 0; a1 = 1 - a0;
00144             if (a1)
00145             {
00146                 m11 = dotA0B1;
00147                 k1 = extBA0B1;
00148                 negate = -dotA1B0 < 0;
00149             }
00150             else
00151             {
00152                 m11 = dotA0B0;
00153                 k1 = extBA0B0;
00154                 negate = -dotA1B1 < 0;
00155             }
00156             center = -delta;
00157             break;
00158 
00159         case PB0:
00160             normal = b.Axis(0);
00161             axis0 = 0; axis1 = 1;
00162             normal2 = normal;
00163             reference = &b; incident = &a;
00164             a0 = absDotA1B0 > absDotA0B0 ? 1 : 0; a1 = 1 - a0;
00165             if (a1)
00166             {
00167                 m11 = dotA1B1;
00168                 k1 = extAA1B1;
00169                 negate = dotA0B0 < 0;
00170             }
00171             else
00172             {
00173                 m11 = dotA0B1;
00174                 k1 = extAA0B1;
00175                 negate = dotA1B0 < 0;
00176             }
00177             center = delta;
00178             break;
00179 
00180         case PB1:
00181             normal = b.Axis(1);
00182             axis0 = 1; axis1 = 0;
00183             normal2 = normal;
00184             reference = &b; incident = &a;
00185             a0 = absDotA1B1 > absDotA0B1 ? 1 : 0; a1 = 1 - a0;
00186             if (a1)
00187             {
00188                 m11 = dotA1B0;
00189                 k1 = extAA1B0;
00190                 negate = dotA0B1 < 0;
00191             }
00192             else
00193             {
00194                 m11 = dotA0B0;
00195                 k1 = extAA0B0;
00196                 negate = dotA1B1 < 0;
00197             }
00198             center = delta;
00199             break;
00200 
00201         case NA0:
00202             normal = -a.Axis(0);
00203             axis0 = 0; axis1 = 1;
00204             normal2 = -normal;
00205             reference = &a; incident = &b;
00206             a0 = absDotA0B1 > absDotA0B0 ? 1 : 0; a1 = 1 - a0;
00207             if (a1)
00208             {
00209                 m11 = dotA1B1;
00210                 k1 = extBA1B1;
00211                 negate = dotA0B0 < 0;
00212             }
00213             else
00214             {
00215                 m11 = dotA1B0;
00216                 k1 = extBA1B0;
00217                 negate = dotA0B1 < 0;
00218             }
00219             center = -delta;
00220             break;
00221 
00222         case NA1:
00223             normal = -a.Axis(1);
00224             axis0 = 1; axis1 = 0;
00225             normal2 = -normal;
00226             reference = &a; incident = &b;
00227             a0 = absDotA1B1 > absDotA1B0 ? 1 : 0; a1 = 1 - a0;
00228             if (a1)
00229             {
00230                 m11 = dotA0B1;
00231                 k1 = extBA0B1;
00232                 negate = dotA1B0 < 0;
00233             }
00234             else
00235             {
00236                 m11 = dotA0B0;
00237                 k1 = extBA0B0;
00238                 negate = dotA1B1 < 0;
00239             }
00240             center = -delta;
00241             break;
00242 
00243         case NB0:
00244             normal = -b.Axis(0);
00245             axis0 = 0; axis1 = 1;
00246             normal2 = normal;
00247             reference = &b; incident = &a;
00248             a0 = absDotA1B0 > absDotA0B0 ? 1 : 0; a1 = 1 - a0;
00249             if (a1)
00250             {
00251                 m11 = dotA1B1;
00252                 k1 = extAA1B1;
00253                 negate = -dotA0B0 < 0;
00254             }
00255             else
00256             {
00257                 m11 = dotA0B1;
00258                 k1 = extAA0B1;
00259                 negate = -dotA1B0 < 0;
00260             }
00261             center = delta;
00262             break;
00263 
00264         case NB1:
00265             normal = -b.Axis(1);
00266             axis0 = 1; axis1 = 0;
00267             normal2 = normal;
00268             reference = &b; incident = &a;
00269             a0 = absDotA1B1 > absDotA0B1 ? 1 : 0; a1 = 1 - a0;
00270             if (a1)
00271             {
00272                 m11 = dotA1B0;
00273                 k1 = extAA1B0;
00274                 negate = -dotA0B1 < 0;
00275             }
00276             else
00277             {
00278                 m11 = dotA0B0;
00279                 k1 = extAA0B0;
00280                 negate = -dotA1B1 < 0;
00281             }
00282             center = delta;
00283             break;
00284     }
00285 
00286     // compute center point of incident face, in reference-face coordinates
00287     if (negate)
00288         center += incident->EAxis(a0);
00289     else
00290         center -= incident->EAxis(a0);
00291 
00292     // find the intersection points
00293     float collisions[2];
00294     int count = 0;
00295     {
00296         float c1 = dot(center, reference->Axis(axis1));
00297         float a = c1 - k1;
00298         float b = c1 + k1;
00299         float w = reference->Extent(axis1);
00300 
00301         if (w > a && w < b)
00302             collisions[count++] = w - c1;
00303         if (a < w && a > -w)
00304             collisions[count++] = -k1;
00305         if (-w > a && -w < b)
00306             collisions[count++] = -w - c1;
00307         if (b < w && b > -w)
00308             collisions[count++] = k1;
00309     }
00310 
00311     // Count should be 2 or less.  It is almost always equal to 2.
00312     assert(count < 3);
00313 
00314     for (int j = 0; j < count; ++j)
00315     {
00316         float k1 = collisions[j] / m11;
00317         vec2 point = center + incident->Axis(a1) * k1;
00318         float depth = reference->Extent(axis0) - dot(normal2, point);
00319         if (depth >= 0)
00320             contacts.AddContact(point + reference->Center(), normal, depth);
00321     }
00322 }

Generated on Sat Jan 13 17:20:21 2007 for Flatland by doxygen 1.5.1