internal PolygonShape(ShapeDef def) : base(def) { Box2DXDebug.Assert(def.Type == ShapeType.PolygonShape); _type = ShapeType.PolygonShape; PolygonDef poly = (PolygonDef)def; // Get the vertices transformed into the body frame. _vertexCount = poly.VertexCount; Box2DXDebug.Assert(3 <= _vertexCount && _vertexCount <= Settings.MaxPolygonVertices); // Copy vertices. for (int i = 0; i < _vertexCount; ++i) { _vertices[i] = poly.Vertices[i]; } // Compute normals. Ensure the edges have non-zero length. for (int i = 0; i < _vertexCount; ++i) { int i1 = i; int i2 = i + 1 < _vertexCount ? i + 1 : 0; Vec2 edge = _vertices[i2] - _vertices[i1]; Box2DXDebug.Assert(edge.LengthSquared() > Common.Settings.FLT_EPSILON * Common.Settings.FLT_EPSILON); _normals[i] = Vec2.Cross(edge, 1.0f); _normals[i].Normalize(); } #if DEBUG // Ensure the polygon is convex. for (int i = 0; i < _vertexCount; ++i) { for (int j = 0; j < _vertexCount; ++j) { // Don't check vertices on the current edge. if (j == i || j == (i + 1) % _vertexCount) { continue; } // Your polygon is non-convex (it has an indentation). // Or your polygon is too skinny. float s = Vec2.Dot(_normals[i], _vertices[j] - _vertices[i]); Box2DXDebug.Assert(s < -Settings.LinearSlop); } } // Ensure the polygon is counter-clockwise. for (int i = 1; i < _vertexCount; ++i) { float cross = Vec2.Cross(_normals[i - 1], _normals[i]); // Keep asinf happy. cross = Common.Math.Clamp(cross, -1.0f, 1.0f); // You have consecutive edges that are almost parallel on your polygon. float angle = (float)System.Math.Asin(cross); Box2DXDebug.Assert(angle > Settings.AngularSlop); } #endif // Compute the polygon centroid. _centroid = ComputeCentroid(poly.Vertices, poly.VertexCount); // Compute the oriented bounding box. ComputeOBB(out _obb, _vertices, _vertexCount); // Create core polygon shape by shifting edges inward. // Also compute the min/max radius for CCD. for (int i = 0; i < _vertexCount; ++i) { int i1 = i - 1 >= 0 ? i - 1 : _vertexCount - 1; int i2 = i; Vec2 n1 = _normals[i1]; Vec2 n2 = _normals[i2]; Vec2 v = _vertices[i] - _centroid; ; Vec2 d = new Vec2(); d.X = Vec2.Dot(n1, v) - Settings.ToiSlop; d.Y = Vec2.Dot(n2, v) - Settings.ToiSlop; // Shifting the edge inward by b2_toiSlop should // not cause the plane to pass the centroid. // Your shape has a radius/extent less than b2_toiSlop. Box2DXDebug.Assert(d.X >= 0.0f); Box2DXDebug.Assert(d.Y >= 0.0f); Mat22 A = new Mat22(); A.Col1.X = n1.X; A.Col2.X = n1.Y; A.Col1.Y = n2.X; A.Col2.Y = n2.Y; _coreVertices[i] = A.Solve(d) + _centroid; } }