/* * Farseer Physics Engine based on Box2D.XNA port: * Copyright (c) 2010 Ian Qvist * * Box2D.XNA port of Box2D: * Copyright (c) 2009 Brandon Furtwangler, Nathan Furtwangler * * Original source Box2D: * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com * * This software is provided 'as-is', without any express or implied * warranty. In no event will the authors be held liable for any damages * arising from the use of this software. * Permission is granted to anyone to use this software for any purpose, * including commercial applications, and to alter it and redistribute it * freely, subject to the following restrictions: * 1. The origin of this software must not be misrepresented; you must not * claim that you wrote the original software. If you use this software * in a product, an acknowledgment in the product documentation would be * appreciated but is not required. * 2. Altered source versions must be plainly marked as such, and must not be * misrepresented as being the original software. * 3. This notice may not be removed or altered from any source distribution. */ using System.Diagnostics; using FarseerPhysics.Common; using Microsoft.Xna.Framework; namespace FarseerPhysics.Collision.Shapes { /// /// A loop Shape is a free form sequence of line segments that form a circular list. /// The loop may cross upon itself, but this is not recommended for smooth collision. /// The loop has double sided collision, so you can use inside and outside collision. /// Therefore, you may use any winding order. /// public class LoopShape : Shape { private static EdgeShape _edgeShape = new EdgeShape(); /// /// The vertices. These are not owned/freed by the loop Shape. /// public Vertices Vertices; private LoopShape() : base(0) { ShapeType = ShapeType.Loop; _radius = Settings.PolygonRadius; } public LoopShape(Vertices vertices) : base(0) { ShapeType = ShapeType.Loop; _radius = Settings.PolygonRadius; #pragma warning disable 162 if (Settings.ConserveMemory) Vertices = vertices; else // Copy vertices. Vertices = new Vertices(vertices); #pragma warning restore 162 } public override int ChildCount { get { return Vertices.Count; } } public override Shape Clone() { LoopShape loop = new LoopShape(); loop._density = _density; loop._radius = _radius; loop.Vertices = Vertices; loop.MassData = MassData; return loop; } /// /// Get a child edge. /// /// The edge. /// The index. public void GetChildEdge(ref EdgeShape edge, int index) { Debug.Assert(2 <= Vertices.Count); Debug.Assert(0 <= index && index < Vertices.Count); edge.ShapeType = ShapeType.Edge; edge._radius = _radius; edge.HasVertex0 = true; edge.HasVertex3 = true; int i0 = index - 1 >= 0 ? index - 1 : Vertices.Count - 1; int i1 = index; int i2 = index + 1 < Vertices.Count ? index + 1 : 0; int i3 = index + 2; while (i3 >= Vertices.Count) { i3 -= Vertices.Count; } edge.Vertex0 = Vertices[i0]; edge.Vertex1 = Vertices[i1]; edge.Vertex2 = Vertices[i2]; edge.Vertex3 = Vertices[i3]; } /// /// Test a point for containment in this shape. This only works for convex shapes. /// /// The shape world transform. /// a point in world coordinates. /// True if the point is inside the shape public override bool TestPoint(ref Transform transform, ref Vector2 point) { return false; } /// /// Cast a ray against a child shape. /// /// The ray-cast results. /// The ray-cast input parameters. /// The transform to be applied to the shape. /// The child shape index. /// True if the ray-cast hits the shape public override bool RayCast(out RayCastOutput output, ref RayCastInput input, ref Transform transform, int childIndex) { Debug.Assert(childIndex < Vertices.Count); int i1 = childIndex; int i2 = childIndex + 1; if (i2 == Vertices.Count) { i2 = 0; } _edgeShape.Vertex1 = Vertices[i1]; _edgeShape.Vertex2 = Vertices[i2]; return _edgeShape.RayCast(out output, ref input, ref transform, 0); } /// /// Given a transform, compute the associated axis aligned bounding box for a child shape. /// /// The aabb results. /// The world transform of the shape. /// The child shape index. public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex) { Debug.Assert(childIndex < Vertices.Count); int i1 = childIndex; int i2 = childIndex + 1; if (i2 == Vertices.Count) { i2 = 0; } Vector2 v1 = MathUtils.Multiply(ref transform, Vertices[i1]); Vector2 v2 = MathUtils.Multiply(ref transform, Vertices[i2]); aabb.LowerBound = Vector2.Min(v1, v2); aabb.UpperBound = Vector2.Max(v1, v2); } /// /// Chains have zero mass. /// public override void ComputeProperties() { //Does nothing. Loop shapes don't have properties. } public override float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 sc) { sc = Vector2.Zero; return 0; } } }