/// Implement Shape. public override Shape Clone() { var edge = new EdgeShape(); edge._hasVertex0 = _hasVertex0; edge._hasVertex3 = _hasVertex3; edge._radius = _radius; edge._vertex0 = _vertex0; edge._vertex1 = _vertex1; edge._vertex2 = _vertex2; edge._vertex3 = _vertex3; return edge; }
/// <summary> Get a child edge. /// </summary> public void GetChildEdge(ref EdgeShape edge, int index) { Debug.Assert(2 <= _count); Debug.Assert(0 <= index && index < _count); edge.ShapeType = ShapeType.Edge; edge._radius = _radius; edge._hasVertex0 = true; edge._hasVertex3 = true; int i0 = index - 1 >= 0 ? index - 1 : _count - 1; int i1 = index; int i2 = index + 1 < _count ? index + 1 : 0; int i3 = index + 2; while (i3 >= _count) { i3 -= _count; } edge._vertex0 = _vertices[i0]; edge._vertex1 = _vertices[i1]; edge._vertex2 = _vertices[i2]; edge._vertex3 = _vertices[i3]; }
public EdgeTest() { { BodyDef bd = new BodyDef(); Body ground = _world.CreateBody(bd); Vector2 v1 = new Vector2(-10.0f, 0.0f); Vector2 v2 = new Vector2(-7.0f, -1.0f); Vector2 v3 = new Vector2(-4.0f, 0.0f); Vector2 v4 = new Vector2(0.0f, 0.0f); Vector2 v5 = new Vector2(4.0f, 0.0f); Vector2 v6 = new Vector2(7.0f, 1.0f); Vector2 v7 = new Vector2(10.0f, 0.0f); EdgeShape shape = new EdgeShape(); shape.Set(v1, v2); //shape._index1 = 0; //shape._index2 = 1; shape._hasVertex3 = true; shape._vertex3 = v3; ground.CreateFixture(shape, 0.0f); shape.Set(v2, v3); //shape._index1 = 1; //shape._index2 = 2; shape._hasVertex0 = true; shape._hasVertex3 = true; shape._vertex0 = v1; shape._vertex3 = v4; ground.CreateFixture(shape, 0.0f); shape.Set(v3, v4); //shape._index1 = 2; //shape._index2 = 3; shape._hasVertex0 = true; shape._hasVertex3 = true; shape._vertex0 = v2; shape._vertex3 = v5; ground.CreateFixture(shape, 0.0f); shape.Set(v4, v5); //shape._index1 = 3; //shape._index2 = 4; shape._hasVertex0 = true; shape._hasVertex3 = true; shape._vertex0 = v3; shape._vertex3 = v6; ground.CreateFixture(shape, 0.0f); shape.Set(v5, v6); //shape._index1 = 4; //shape._index2 = 5; shape._hasVertex0 = true; shape._hasVertex3 = true; shape._vertex0 = v4; shape._vertex3 = v7; ground.CreateFixture(shape, 0.0f); shape.Set(v6, v7); //shape._index1 = 5; //shape._index2 = 6; shape._hasVertex0 = true; shape._vertex0 = v5; ground.CreateFixture(shape, 0.0f); } { BodyDef bd = new BodyDef(); bd.type = BodyType.Dynamic; bd.position = new Vector2(-0.5f, 0.5f); bd.allowSleep = false; Body body = _world.CreateBody(bd); CircleShape shape = new CircleShape(); shape._radius = 0.5f; body.CreateFixture(shape, 1.0f); } { BodyDef bd = new BodyDef(); bd.type = BodyType.Dynamic; bd.position = new Vector2(0.5f, 0.5f); bd.allowSleep = false; Body body = _world.CreateBody(bd); PolygonShape shape = new PolygonShape(); shape.SetAsBox(0.5f, 0.5f); body.CreateFixture(shape, 1.0f); } }
public static void CollideEdgeAndPolygon(ref Manifold manifold, EdgeShape edgeA, ref Transform xfA, PolygonShape polygonB_in, ref Transform xfB) { manifold._pointCount = 0; Transform xf; MathUtils.MultiplyT(ref xfA, ref xfB, out xf); // Create a polygon for edge shape A s_polygonA.SetAsEdge(edgeA._vertex1, edgeA._vertex2); // Build polygonB in frame A s_polygonB._radius = polygonB_in._radius; s_polygonB._vertexCount = polygonB_in._vertexCount; s_polygonB._centroid = MathUtils.Multiply(ref xf, polygonB_in._centroid); for (int i = 0; i < s_polygonB._vertexCount; ++i) { s_polygonB._vertices[i] = MathUtils.Multiply(ref xf, polygonB_in._vertices[i]); s_polygonB._normals[i] = MathUtils.Multiply(ref xf.R, polygonB_in._normals[i]); } float totalRadius = s_polygonA._radius + s_polygonB._radius; // Edge geometry Vector2 v1 = edgeA._vertex1; Vector2 v2 = edgeA._vertex2; Vector2 e = v2 - v1; Vector2 edgeNormal = new Vector2(e.Y, -e.X); edgeNormal.Normalize(); // Determine side bool isFrontSide = Vector2.Dot(edgeNormal, s_polygonB._centroid - v1) >= 0.0f; if (isFrontSide == false) { edgeNormal = -edgeNormal; } // Compute primary separating axis EPAxis edgeAxis = ComputeEdgeSeperation(v1, v2, edgeNormal, s_polygonB, totalRadius); if (edgeAxis.separation > totalRadius) { // Shapes are separated return; } // Classify adjacent edges FixedArray2<EdgeType> types = new FixedArray2<EdgeType>(); //types[0] = EdgeType.Isolated; //types[1] = EdgeType.Isolated; if (edgeA._hasVertex0) { Vector2 v0 = edgeA._vertex0; float s = Vector2.Dot(edgeNormal, v0 - v1); if (s > 0.1f * Settings.b2_linearSlop) { types[0] = EdgeType.Concave; } else if (s >= -0.1f * Settings.b2_linearSlop) { types[0] = EdgeType.Flat; } else { types[0] = EdgeType.Convex; } } if (edgeA._hasVertex3) { Vector2 v3 = edgeA._vertex3; float s = Vector2.Dot(edgeNormal, v3 - v2); if (s > 0.1f * Settings.b2_linearSlop) { types[1] = EdgeType.Concave; } else if (s >= -0.1f * Settings.b2_linearSlop) { types[1] = EdgeType.Flat; } else { types[1] = EdgeType.Convex; } } if (types[0] == EdgeType.Convex) { // Check separation on previous edge. Vector2 v0 = edgeA._vertex0; Vector2 e0 = v1 - v0; Vector2 n0 = new Vector2(e0.Y, -e0.X); n0.Normalize(); if (isFrontSide == false) { n0 = -n0; } EPAxis axis1 = ComputeEdgeSeperation(v0, v1, n0, s_polygonB, totalRadius); if (axis1.separation > edgeAxis.separation) { // The polygon should collide with previous edge return; } } if (types[1] == EdgeType.Convex) { // Check separation on next edge. Vector2 v3 = edgeA._vertex3; Vector2 e2 = v3 - v2; Vector2 n2 = new Vector2(e2.Y, -e2.X); n2.Normalize(); if (isFrontSide == false) { n2 = -n2; } EPAxis axis2 = ComputeEdgeSeperation(v2, v3, n2, s_polygonB, totalRadius); if (axis2.separation > edgeAxis.separation) { // The polygon should collide with the next edge return; } } EPAxis polygonAxis = ComputePolygonSeperation(v1, v2, edgeNormal, s_polygonB, totalRadius); if (polygonAxis.separation > totalRadius) { return; } // Use hysteresis for jitter reduction. float k_relativeTol = 0.98f; float k_absoluteTol = 0.001f; EPAxis primaryAxis; if (polygonAxis.separation > k_relativeTol * edgeAxis.separation + k_absoluteTol) { primaryAxis = polygonAxis; } else { primaryAxis = edgeAxis; } PolygonShape poly1; PolygonShape poly2; if (primaryAxis.type == EPAxisType.EdgeA) { poly1 = s_polygonA; poly2 = s_polygonB; if (isFrontSide == false) { primaryAxis.index = 1; } manifold._type = ManifoldType.FaceA; } else { poly1 = s_polygonB; poly2 = s_polygonA; manifold._type = ManifoldType.FaceB; } int edge1 = primaryAxis.index; FixedArray2<ClipVertex> incidentEdge = new FixedArray2<ClipVertex>(); FindIncidentEdge(ref incidentEdge, poly1, primaryAxis.index, poly2); int count1 = poly1._vertexCount; int iv1 = edge1; int iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0; Vector2 v11 = poly1._vertices[iv1]; Vector2 v12 = poly1._vertices[iv2]; Vector2 tangent = v12 - v11; tangent.Normalize(); Vector2 normal = MathUtils.Cross(tangent, 1.0f); Vector2 planePoint = 0.5f * (v11 + v12); // Face offset. float frontOffset = Vector2.Dot(normal, v11); // Side offsets, extended by polytope skin thickness. float sideOffset1 = -Vector2.Dot(tangent, v11) + totalRadius; float sideOffset2 = Vector2.Dot(tangent, v12) + totalRadius; // Clip incident edge against extruded edge1 side edges. FixedArray2<ClipVertex> clipPoints1; FixedArray2<ClipVertex> clipPoints2; int np; // Clip to box side 1 np = ClipSegmentToLine(out clipPoints1, ref incidentEdge, -tangent, sideOffset1, iv1); if (np < Settings.b2_maxManifoldPoints) { return; } // Clip to negative box side 1 np = ClipSegmentToLine(out clipPoints2, ref clipPoints1, tangent, sideOffset2, iv2); if (np < Settings.b2_maxManifoldPoints) { return; } // Now clipPoints2 contains the clipped points. if (primaryAxis.type == EPAxisType.EdgeA) { manifold._localNormal = normal; manifold._localPoint = planePoint; } else { manifold._localNormal = MathUtils.MultiplyT(ref xf.R, normal); manifold._localPoint = MathUtils.MultiplyT(ref xf, planePoint); } int pointCount = 0; for (int i = 0; i < Settings.b2_maxManifoldPoints; ++i) { float separation; separation = Vector2.Dot(normal, clipPoints2[i].v) - frontOffset; if (separation <= totalRadius) { ManifoldPoint cp = manifold._points[pointCount]; if (primaryAxis.type == EPAxisType.EdgeA) { cp.LocalPoint = MathUtils.MultiplyT(ref xf, clipPoints2[i].v); cp.Id = clipPoints2[i].id; } else { cp.LocalPoint = clipPoints2[i].v; cp.Id.Features.typeA = clipPoints2[i].id.Features.typeB; cp.Id.Features.typeB = clipPoints2[i].id.Features.typeA; cp.Id.Features.indexA = clipPoints2[i].id.Features.indexB; cp.Id.Features.indexB = clipPoints2[i].id.Features.indexA; } manifold._points[pointCount] = cp; if (cp.Id.Features.typeA == (byte)ContactFeatureType.Vertex && types[cp.Id.Features.indexA] == EdgeType.Flat) { continue; } ++pointCount; } } manifold._pointCount = pointCount; }
// Compute contact points for edge versus circle. // This accounts for edge connectivity. public static void CollideEdgeAndCircle(ref Manifold manifold, EdgeShape edgeA, ref Transform xfA, CircleShape circleB, ref Transform xfB) { manifold._pointCount = 0; // Compute circle in frame of edge Vector2 Q = MathUtils.MultiplyT(ref xfA, MathUtils.Multiply(ref xfB, circleB._p)); Vector2 A = edgeA._vertex1, B = edgeA._vertex2; Vector2 e = B - A; // Barycentric coordinates float u = Vector2.Dot(e, B - Q); float v = Vector2.Dot(e, Q - A); float radius = edgeA._radius + circleB._radius; ContactFeature cf; cf.indexB = 0; cf.typeB = (byte)ContactFeatureType.Vertex; Vector2 P, d; // Region A if (v <= 0.0f) { P = A; d = Q - P; float dd = Vector2.Dot(d, d); if (dd > radius * radius) { return; } // Is there an edge connected to A? if (edgeA._hasVertex0) { Vector2 A1 = edgeA._vertex0; Vector2 B1 = A; Vector2 e1 = B1 - A1; float u1 = Vector2.Dot(e1, B1 - Q); // Is the circle in Region AB of the previous edge? if (u1 > 0.0f) { return; } } cf.indexA = 0; cf.typeA = (byte)ContactFeatureType.Vertex; manifold._pointCount = 1; manifold._type = ManifoldType.Circles; manifold._localNormal = Vector2.Zero; manifold._localPoint = P; var mp = new ManifoldPoint(); mp.Id.Key = 0; mp.Id.Features = cf; mp.LocalPoint = circleB._p; manifold._points[0] = mp; return; } // Region B if (u <= 0.0f) { P = B; d = Q - P; float dd = Vector2.Dot(d, d); if (dd > radius * radius) { return; } // Is there an edge connected to B? if (edgeA._hasVertex3) { Vector2 B2 = edgeA._vertex3; Vector2 A2 = B; Vector2 e2 = B2 - A2; float v2 = Vector2.Dot(e2, Q - A2); // Is the circle in Region AB of the next edge? if (v2 > 0.0f) { return; } } cf.indexA = 1; cf.typeA = (byte)ContactFeatureType.Vertex; manifold._pointCount = 1; manifold._type = ManifoldType.Circles; manifold._localNormal = Vector2.Zero; manifold._localPoint = P; var mp = new ManifoldPoint(); mp.Id.Key = 0; mp.Id.Features = cf; mp.LocalPoint = circleB._p; manifold._points[0] = mp; return; } // Region AB float den = Vector2.Dot(e, e); Debug.Assert(den > 0.0f); P = (1.0f / den) * (u * A + v * B); d = Q - P; float dd2 = Vector2.Dot(d, d); if (dd2 > radius * radius) { return; } Vector2 n = new Vector2(-e.Y, e.X); if (Vector2.Dot(n, Q - A) < 0.0f) { n = new Vector2(-n.X, -n.Y); } n.Normalize(); cf.indexA = 0; cf.typeA = (byte)ContactFeatureType.Face; manifold._pointCount = 1; manifold._type = ManifoldType.FaceA; manifold._localNormal = n; manifold._localPoint = A; var mp2 = new ManifoldPoint(); mp2.Id.Key = 0; mp2.Id.Features = cf; mp2.LocalPoint = circleB._p; manifold._points[0] = mp2; }
private bool IsLegalPosition() { EdgeShape shape = new EdgeShape(); bool isLegal = false; if (mBuildingObjectType == PlayerData.ObjectType.Gun) { isLegal = true; } else { isLegal = true; List<Box> boxes = mGameObjectCollection.Boxes; Body buildingBlockBody = ((Box)mBuildingBlock).mBody; Shape shape1 = buildingBlockBody.GetFixtureList().GetShape(); Transform transform1, transform2; buildingBlockBody.GetTransform(out transform1); for (int i = 0; i < boxes.Count; i++) { Body body = boxes[i].mBody; Shape shape2 = body.GetFixtureList().GetShape(); body.GetTransform(out transform2); bool isOverlap = AABB.TestOverlap(shape1, 0, shape2, 0, ref transform1, ref transform2); if (isOverlap) { isLegal = false; break; } } } return isLegal; }
/// Get a child edge. public void GetChildEdge(ref EdgeShape edge, int index) { Debug.Assert(2 <= _count); Debug.Assert(0 <= index && index < _count); edge.ShapeType = ShapeType.Edge; edge._radius = _radius; edge._hasVertex0 = true; edge._hasVertex3 = true; int i0 = index - 1 >= 0 ? index - 1 : _count - 1; int i1 = index; int i2 = index + 1 < _count ? index + 1 : 0; int i3 = index + 2; while (i3 >= _count) { i3 -= _count; } edge._vertex0 = _vertices[i0]; edge._vertex1 = _vertices[i1]; edge._vertex2 = _vertices[i2]; edge._vertex3 = _vertices[i3]; }
private Body CreatePhysicalViewBounds() { var bodyDef = new BodyDef(); bodyDef.type = BodyType.Static; var body = World.CreateBody(bodyDef); var edges = new EdgeShape[]{new EdgeShape(), new EdgeShape(), new EdgeShape(), new EdgeShape()}; var viewport = game.GraphicsDevice.Viewport; var X = ConvertToBox2D(viewport.Width / 2); var Y = ConvertToBox2D(viewport.Height / 2); edges[0].Set(new Vector2(-X, -Y), new Vector2(+X, -Y)); edges[1].Set(new Vector2(+X, -Y), new Vector2(+X, +Y)); edges[2].Set(new Vector2(+X, +Y), new Vector2(-X, +Y)); edges[3].Set(new Vector2(-X, +Y), new Vector2(-X, -Y)); foreach (var edge in edges) { var fixtureDef = new FixtureDef(); fixtureDef.shape = edge; fixtureDef.friction = 0.0f; body.CreateFixture(fixtureDef); } return body; }