File indexing completed on 2024-05-19 14:56:21
0001 /* 0002 * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org 0003 * 0004 * This software is provided 'as-is', without any express or implied 0005 * warranty. In no event will the authors be held liable for any damages 0006 * arising from the use of this software. 0007 * Permission is granted to anyone to use this software for any purpose, 0008 * including commercial applications, and to alter it and redistribute it 0009 * freely, subject to the following restrictions: 0010 * 1. The origin of this software must not be misrepresented; you must not 0011 * claim that you wrote the original software. If you use this software 0012 * in a product, an acknowledgment in the product documentation would be 0013 * appreciated but is not required. 0014 * 2. Altered source versions must be plainly marked as such, and must not be 0015 * misrepresented as being the original software. 0016 * 3. This notice may not be removed or altered from any source distribution. 0017 */ 0018 0019 #ifndef B2_COLLISION_H 0020 #define B2_COLLISION_H 0021 0022 #include <Box2D/Common/b2Math.h> 0023 #include <limits.h> 0024 0025 /// @file 0026 /// Structures and functions used for computing contact points, distance 0027 /// queries, and TOI queries. 0028 0029 class b2Shape; 0030 class b2CircleShape; 0031 class b2EdgeShape; 0032 class b2PolygonShape; 0033 0034 const uint8 b2_nullFeature = UCHAR_MAX; 0035 0036 /// The features that intersect to form the contact point 0037 /// This must be 4 bytes or less. 0038 struct b2ContactFeature 0039 { 0040 enum Type 0041 { 0042 e_vertex = 0, 0043 e_face = 1 0044 }; 0045 0046 uint8 indexA; ///< Feature index on shapeA 0047 uint8 indexB; ///< Feature index on shapeB 0048 uint8 typeA; ///< The feature type on shapeA 0049 uint8 typeB; ///< The feature type on shapeB 0050 }; 0051 0052 /// Contact ids to facilitate warm starting. 0053 union b2ContactID 0054 { 0055 b2ContactFeature cf; 0056 uint32 key; ///< Used to quickly compare contact ids. 0057 }; 0058 0059 /// A manifold point is a contact point belonging to a contact 0060 /// manifold. It holds details related to the geometry and dynamics 0061 /// of the contact points. 0062 /// The local point usage depends on the manifold type: 0063 /// -e_circles: the local center of circleB 0064 /// -e_faceA: the local center of cirlceB or the clip point of polygonB 0065 /// -e_faceB: the clip point of polygonA 0066 /// This structure is stored across time steps, so we keep it small. 0067 /// Note: the impulses are used for internal caching and may not 0068 /// provide reliable contact forces, especially for high speed collisions. 0069 struct b2ManifoldPoint 0070 { 0071 b2Vec2 localPoint; ///< usage depends on manifold type 0072 float32 normalImpulse; ///< the non-penetration impulse 0073 float32 tangentImpulse; ///< the friction impulse 0074 b2ContactID id; ///< uniquely identifies a contact point between two shapes 0075 }; 0076 0077 /// A manifold for two touching convex shapes. 0078 /// Box2D supports multiple types of contact: 0079 /// - clip point versus plane with radius 0080 /// - point versus point with radius (circles) 0081 /// The local point usage depends on the manifold type: 0082 /// -e_circles: the local center of circleA 0083 /// -e_faceA: the center of faceA 0084 /// -e_faceB: the center of faceB 0085 /// Similarly the local normal usage: 0086 /// -e_circles: not used 0087 /// -e_faceA: the normal on polygonA 0088 /// -e_faceB: the normal on polygonB 0089 /// We store contacts in this way so that position correction can 0090 /// account for movement, which is critical for continuous physics. 0091 /// All contact scenarios must be expressed in one of these types. 0092 /// This structure is stored across time steps, so we keep it small. 0093 struct b2Manifold 0094 { 0095 enum Type 0096 { 0097 e_circles, 0098 e_faceA, 0099 e_faceB 0100 }; 0101 0102 b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact 0103 b2Vec2 localNormal; ///< not use for Type::e_points 0104 b2Vec2 localPoint; ///< usage depends on manifold type 0105 Type type; 0106 int32 pointCount; ///< the number of manifold points 0107 }; 0108 0109 /// This is used to compute the current state of a contact manifold. 0110 struct b2WorldManifold 0111 { 0112 /// Evaluate the manifold with supplied transforms. This assumes 0113 /// modest motion from the original state. This does not change the 0114 /// point count, impulses, etc. The radii must come from the shapes 0115 /// that generated the manifold. 0116 void Initialize(const b2Manifold* manifold, 0117 const b2Transform& xfA, float32 radiusA, 0118 const b2Transform& xfB, float32 radiusB); 0119 0120 b2Vec2 normal; ///< world vector pointing from A to B 0121 b2Vec2 points[b2_maxManifoldPoints]; ///< world contact point (point of intersection) 0122 float32 separations[b2_maxManifoldPoints]; ///< a negative value indicates overlap, in meters 0123 }; 0124 0125 /// This is used for determining the state of contact points. 0126 enum b2PointState 0127 { 0128 b2_nullState, ///< point does not exist 0129 b2_addState, ///< point was added in the update 0130 b2_persistState, ///< point persisted across the update 0131 b2_removeState ///< point was removed in the update 0132 }; 0133 0134 /// Compute the point states given two manifolds. The states pertain to the transition from manifold1 0135 /// to manifold2. So state1 is either persist or remove while state2 is either add or persist. 0136 void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], 0137 const b2Manifold* manifold1, const b2Manifold* manifold2); 0138 0139 /// Used for computing contact manifolds. 0140 struct b2ClipVertex 0141 { 0142 b2Vec2 v; 0143 b2ContactID id; 0144 }; 0145 0146 /// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). 0147 struct b2RayCastInput 0148 { 0149 b2Vec2 p1, p2; 0150 float32 maxFraction; 0151 }; 0152 0153 /// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2 0154 /// come from b2RayCastInput. 0155 struct b2RayCastOutput 0156 { 0157 b2Vec2 normal; 0158 float32 fraction; 0159 }; 0160 0161 /// An axis aligned bounding box. 0162 struct b2AABB 0163 { 0164 /// Verify that the bounds are sorted. 0165 bool IsValid() const; 0166 0167 /// Get the center of the AABB. 0168 b2Vec2 GetCenter() const 0169 { 0170 return 0.5f * (lowerBound + upperBound); 0171 } 0172 0173 /// Get the extents of the AABB (half-widths). 0174 b2Vec2 GetExtents() const 0175 { 0176 return 0.5f * (upperBound - lowerBound); 0177 } 0178 0179 /// Get the perimeter length 0180 float32 GetPerimeter() const 0181 { 0182 float32 wx = upperBound.x - lowerBound.x; 0183 float32 wy = upperBound.y - lowerBound.y; 0184 return 2.0f * (wx + wy); 0185 } 0186 0187 /// Combine an AABB into this one. 0188 void Combine(const b2AABB& aabb) 0189 { 0190 lowerBound = b2Min(lowerBound, aabb.lowerBound); 0191 upperBound = b2Max(upperBound, aabb.upperBound); 0192 } 0193 0194 /// Combine two AABBs into this one. 0195 void Combine(const b2AABB& aabb1, const b2AABB& aabb2) 0196 { 0197 lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound); 0198 upperBound = b2Max(aabb1.upperBound, aabb2.upperBound); 0199 } 0200 0201 /// Does this aabb contain the provided AABB. 0202 bool Contains(const b2AABB& aabb) const 0203 { 0204 bool result = true; 0205 result = result && lowerBound.x <= aabb.lowerBound.x; 0206 result = result && lowerBound.y <= aabb.lowerBound.y; 0207 result = result && aabb.upperBound.x <= upperBound.x; 0208 result = result && aabb.upperBound.y <= upperBound.y; 0209 return result; 0210 } 0211 0212 bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const; 0213 0214 b2Vec2 lowerBound; ///< the lower vertex 0215 b2Vec2 upperBound; ///< the upper vertex 0216 }; 0217 0218 /// Compute the collision manifold between two circles. 0219 void b2CollideCircles(b2Manifold* manifold, 0220 const b2CircleShape* circleA, const b2Transform& xfA, 0221 const b2CircleShape* circleB, const b2Transform& xfB); 0222 0223 /// Compute the collision manifold between a polygon and a circle. 0224 void b2CollidePolygonAndCircle(b2Manifold* manifold, 0225 const b2PolygonShape* polygonA, const b2Transform& xfA, 0226 const b2CircleShape* circleB, const b2Transform& xfB); 0227 0228 /// Compute the collision manifold between two polygons. 0229 void b2CollidePolygons(b2Manifold* manifold, 0230 const b2PolygonShape* polygonA, const b2Transform& xfA, 0231 const b2PolygonShape* polygonB, const b2Transform& xfB); 0232 0233 /// Compute the collision manifold between an edge and a circle. 0234 void b2CollideEdgeAndCircle(b2Manifold* manifold, 0235 const b2EdgeShape* polygonA, const b2Transform& xfA, 0236 const b2CircleShape* circleB, const b2Transform& xfB); 0237 0238 /// Compute the collision manifold between an edge and a circle. 0239 void b2CollideEdgeAndPolygon(b2Manifold* manifold, 0240 const b2EdgeShape* edgeA, const b2Transform& xfA, 0241 const b2PolygonShape* circleB, const b2Transform& xfB); 0242 0243 /// Clipping for contact manifolds. 0244 int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], 0245 const b2Vec2& normal, float32 offset, int32 vertexIndexA); 0246 0247 /// Determine if two generic shapes overlap. 0248 bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, 0249 const b2Shape* shapeB, int32 indexB, 0250 const b2Transform& xfA, const b2Transform& xfB); 0251 0252 // ---------------- Inline Functions ------------------------------------------ 0253 0254 inline bool b2AABB::IsValid() const 0255 { 0256 b2Vec2 d = upperBound - lowerBound; 0257 bool valid = d.x >= 0.0f && d.y >= 0.0f; 0258 valid = valid && lowerBound.IsValid() && upperBound.IsValid(); 0259 return valid; 0260 } 0261 0262 inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b) 0263 { 0264 b2Vec2 d1, d2; 0265 d1 = b.lowerBound - a.upperBound; 0266 d2 = a.lowerBound - b.upperBound; 0267 0268 if (d1.x > 0.0f || d1.y > 0.0f) 0269 return false; 0270 0271 if (d2.x > 0.0f || d2.y > 0.0f) 0272 return false; 0273 0274 return true; 0275 } 0276 0277 #endif