Warning, file /education/gcompris/external/qml-box2d/Box2D/Collision/b2CollideCircle.cpp was not indexed or was modified since last indexation (in which case cross-reference links may be missing, inaccurate or erroneous).
0001 /* 0002 * Copyright (c) 2007-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 #include <Box2D/Collision/b2Collision.h> 0020 #include <Box2D/Collision/Shapes/b2CircleShape.h> 0021 #include <Box2D/Collision/Shapes/b2PolygonShape.h> 0022 0023 void b2CollideCircles( 0024 b2Manifold* manifold, 0025 const b2CircleShape* circleA, const b2Transform& xfA, 0026 const b2CircleShape* circleB, const b2Transform& xfB) 0027 { 0028 manifold->pointCount = 0; 0029 0030 b2Vec2 pA = b2Mul(xfA, circleA->m_p); 0031 b2Vec2 pB = b2Mul(xfB, circleB->m_p); 0032 0033 b2Vec2 d = pB - pA; 0034 float32 distSqr = b2Dot(d, d); 0035 float32 rA = circleA->m_radius, rB = circleB->m_radius; 0036 float32 radius = rA + rB; 0037 if (distSqr > radius * radius) 0038 { 0039 return; 0040 } 0041 0042 manifold->type = b2Manifold::e_circles; 0043 manifold->localPoint = circleA->m_p; 0044 manifold->localNormal.SetZero(); 0045 manifold->pointCount = 1; 0046 0047 manifold->points[0].localPoint = circleB->m_p; 0048 manifold->points[0].id.key = 0; 0049 } 0050 0051 void b2CollidePolygonAndCircle( 0052 b2Manifold* manifold, 0053 const b2PolygonShape* polygonA, const b2Transform& xfA, 0054 const b2CircleShape* circleB, const b2Transform& xfB) 0055 { 0056 manifold->pointCount = 0; 0057 0058 // Compute circle position in the frame of the polygon. 0059 b2Vec2 c = b2Mul(xfB, circleB->m_p); 0060 b2Vec2 cLocal = b2MulT(xfA, c); 0061 0062 // Find the min separating edge. 0063 int32 normalIndex = 0; 0064 float32 separation = -b2_maxFloat; 0065 float32 radius = polygonA->m_radius + circleB->m_radius; 0066 int32 vertexCount = polygonA->m_count; 0067 const b2Vec2* vertices = polygonA->m_vertices; 0068 const b2Vec2* normals = polygonA->m_normals; 0069 0070 for (int32 i = 0; i < vertexCount; ++i) 0071 { 0072 float32 s = b2Dot(normals[i], cLocal - vertices[i]); 0073 0074 if (s > radius) 0075 { 0076 // Early out. 0077 return; 0078 } 0079 0080 if (s > separation) 0081 { 0082 separation = s; 0083 normalIndex = i; 0084 } 0085 } 0086 0087 // Vertices that subtend the incident face. 0088 int32 vertIndex1 = normalIndex; 0089 int32 vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; 0090 b2Vec2 v1 = vertices[vertIndex1]; 0091 b2Vec2 v2 = vertices[vertIndex2]; 0092 0093 // If the center is inside the polygon ... 0094 if (separation < b2_epsilon) 0095 { 0096 manifold->pointCount = 1; 0097 manifold->type = b2Manifold::e_faceA; 0098 manifold->localNormal = normals[normalIndex]; 0099 manifold->localPoint = 0.5f * (v1 + v2); 0100 manifold->points[0].localPoint = circleB->m_p; 0101 manifold->points[0].id.key = 0; 0102 return; 0103 } 0104 0105 // Compute barycentric coordinates 0106 float32 u1 = b2Dot(cLocal - v1, v2 - v1); 0107 float32 u2 = b2Dot(cLocal - v2, v1 - v2); 0108 if (u1 <= 0.0f) 0109 { 0110 if (b2DistanceSquared(cLocal, v1) > radius * radius) 0111 { 0112 return; 0113 } 0114 0115 manifold->pointCount = 1; 0116 manifold->type = b2Manifold::e_faceA; 0117 manifold->localNormal = cLocal - v1; 0118 manifold->localNormal.Normalize(); 0119 manifold->localPoint = v1; 0120 manifold->points[0].localPoint = circleB->m_p; 0121 manifold->points[0].id.key = 0; 0122 } 0123 else if (u2 <= 0.0f) 0124 { 0125 if (b2DistanceSquared(cLocal, v2) > radius * radius) 0126 { 0127 return; 0128 } 0129 0130 manifold->pointCount = 1; 0131 manifold->type = b2Manifold::e_faceA; 0132 manifold->localNormal = cLocal - v2; 0133 manifold->localNormal.Normalize(); 0134 manifold->localPoint = v2; 0135 manifold->points[0].localPoint = circleB->m_p; 0136 manifold->points[0].id.key = 0; 0137 } 0138 else 0139 { 0140 b2Vec2 faceCenter = 0.5f * (v1 + v2); 0141 float32 separation = b2Dot(cLocal - faceCenter, normals[vertIndex1]); 0142 if (separation > radius) 0143 { 0144 return; 0145 } 0146 0147 manifold->pointCount = 1; 0148 manifold->type = b2Manifold::e_faceA; 0149 manifold->localNormal = normals[vertIndex1]; 0150 manifold->localPoint = faceCenter; 0151 manifold->points[0].localPoint = circleB->m_p; 0152 manifold->points[0].id.key = 0; 0153 } 0154 }