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 <Box2D/Collision/b2Collision.h>
00020 #include <Box2D/Collision/b2Distance.h>
00021
00022 void b2WorldManifold::Initialize(const b2Manifold* manifold,
00023 const b2Transform& xfA, float32 radiusA,
00024 const b2Transform& xfB, float32 radiusB)
00025 {
00026 if (manifold->pointCount == 0)
00027 {
00028 return;
00029 }
00030
00031 switch (manifold->type)
00032 {
00033 case b2Manifold::e_circles:
00034 {
00035 normal.Set(1.0f, 0.0f);
00036 b2Vec2 pointA = b2Mul(xfA, manifold->localPoint);
00037 b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint);
00038 if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon)
00039 {
00040 normal = pointB - pointA;
00041 normal.Normalize();
00042 }
00043
00044 b2Vec2 cA = pointA + radiusA * normal;
00045 b2Vec2 cB = pointB - radiusB * normal;
00046 points[0] = 0.5f * (cA + cB);
00047 separations[0] = b2Dot(cB - cA, normal);
00048 }
00049 break;
00050
00051 case b2Manifold::e_faceA:
00052 {
00053 normal = b2Mul(xfA.q, manifold->localNormal);
00054 b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint);
00055
00056 for (int32 i = 0; i < manifold->pointCount; ++i)
00057 {
00058 b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint);
00059 b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal;
00060 b2Vec2 cB = clipPoint - radiusB * normal;
00061 points[i] = 0.5f * (cA + cB);
00062 separations[i] = b2Dot(cB - cA, normal);
00063 }
00064 }
00065 break;
00066
00067 case b2Manifold::e_faceB:
00068 {
00069 normal = b2Mul(xfB.q, manifold->localNormal);
00070 b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint);
00071
00072 for (int32 i = 0; i < manifold->pointCount; ++i)
00073 {
00074 b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint);
00075 b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal;
00076 b2Vec2 cA = clipPoint - radiusA * normal;
00077 points[i] = 0.5f * (cA + cB);
00078 separations[i] = b2Dot(cA - cB, normal);
00079 }
00080
00081
00082 normal = -normal;
00083 }
00084 break;
00085 }
00086 }
00087
00088 void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints],
00089 const b2Manifold* manifold1, const b2Manifold* manifold2)
00090 {
00091 for (int32 i = 0; i < b2_maxManifoldPoints; ++i)
00092 {
00093 state1[i] = b2_nullState;
00094 state2[i] = b2_nullState;
00095 }
00096
00097
00098 for (int32 i = 0; i < manifold1->pointCount; ++i)
00099 {
00100 b2ContactID id = manifold1->points[i].id;
00101
00102 state1[i] = b2_removeState;
00103
00104 for (int32 j = 0; j < manifold2->pointCount; ++j)
00105 {
00106 if (manifold2->points[j].id.key == id.key)
00107 {
00108 state1[i] = b2_persistState;
00109 break;
00110 }
00111 }
00112 }
00113
00114
00115 for (int32 i = 0; i < manifold2->pointCount; ++i)
00116 {
00117 b2ContactID id = manifold2->points[i].id;
00118
00119 state2[i] = b2_addState;
00120
00121 for (int32 j = 0; j < manifold1->pointCount; ++j)
00122 {
00123 if (manifold1->points[j].id.key == id.key)
00124 {
00125 state2[i] = b2_persistState;
00126 break;
00127 }
00128 }
00129 }
00130 }
00131
00132
00133 bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const
00134 {
00135 float32 tmin = -b2_maxFloat;
00136 float32 tmax = b2_maxFloat;
00137
00138 b2Vec2 p = input.p1;
00139 b2Vec2 d = input.p2 - input.p1;
00140 b2Vec2 absD = b2Abs(d);
00141
00142 b2Vec2 normal;
00143
00144 for (int32 i = 0; i < 2; ++i)
00145 {
00146 if (absD(i) < b2_epsilon)
00147 {
00148
00149 if (p(i) < lowerBound(i) || upperBound(i) < p(i))
00150 {
00151 return false;
00152 }
00153 }
00154 else
00155 {
00156 float32 inv_d = 1.0f / d(i);
00157 float32 t1 = (lowerBound(i) - p(i)) * inv_d;
00158 float32 t2 = (upperBound(i) - p(i)) * inv_d;
00159
00160
00161 float32 s = -1.0f;
00162
00163 if (t1 > t2)
00164 {
00165 b2Swap(t1, t2);
00166 s = 1.0f;
00167 }
00168
00169
00170 if (t1 > tmin)
00171 {
00172 normal.SetZero();
00173 normal(i) = s;
00174 tmin = t1;
00175 }
00176
00177
00178 tmax = b2Min(tmax, t2);
00179
00180 if (tmin > tmax)
00181 {
00182 return false;
00183 }
00184 }
00185 }
00186
00187
00188
00189 if (tmin < 0.0f || input.maxFraction < tmin)
00190 {
00191 return false;
00192 }
00193
00194
00195 output->fraction = tmin;
00196 output->normal = normal;
00197 return true;
00198 }
00199
00200
00201 int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2],
00202 const b2Vec2& normal, float32 offset, int32 vertexIndexA)
00203 {
00204
00205 int32 numOut = 0;
00206
00207
00208 float32 distance0 = b2Dot(normal, vIn[0].v) - offset;
00209 float32 distance1 = b2Dot(normal, vIn[1].v) - offset;
00210
00211
00212 if (distance0 <= 0.0f) vOut[numOut++] = vIn[0];
00213 if (distance1 <= 0.0f) vOut[numOut++] = vIn[1];
00214
00215
00216 if (distance0 * distance1 < 0.0f)
00217 {
00218
00219 float32 interp = distance0 / (distance0 - distance1);
00220 vOut[numOut].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v);
00221
00222
00223 vOut[numOut].id.cf.indexA = static_cast<uint8>(vertexIndexA);
00224 vOut[numOut].id.cf.indexB = vIn[0].id.cf.indexB;
00225 vOut[numOut].id.cf.typeA = b2ContactFeature::e_vertex;
00226 vOut[numOut].id.cf.typeB = b2ContactFeature::e_face;
00227 ++numOut;
00228 }
00229
00230 return numOut;
00231 }
00232
00233 bool b2TestOverlap( const b2Shape* shapeA, int32 indexA,
00234 const b2Shape* shapeB, int32 indexB,
00235 const b2Transform& xfA, const b2Transform& xfB)
00236 {
00237 b2DistanceInput input;
00238 input.proxyA.Set(shapeA, indexA);
00239 input.proxyB.Set(shapeB, indexB);
00240 input.transformA = xfA;
00241 input.transformB = xfB;
00242 input.useRadii = true;
00243
00244 b2SimplexCache cache;
00245 cache.count = 0;
00246
00247 b2DistanceOutput output;
00248
00249 b2Distance(&output, &cache, &input);
00250
00251 return output.distance < 10.0f * b2_epsilon;
00252 }