/* * Farseer Physics Engine: * Copyright (c) 2012 Ian Qvist * * Original source Box2D: * Copyright (c) 2006-2011 Erin Catto http://www.box2d.org * * 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; using System.Diagnostics; using FarseerPhysics.Common; using Microsoft.Xna.Framework; namespace FarseerPhysics.Collision.Shapes { /// /// This holds the mass data computed for a shape. /// public struct MassData : IEquatable { /// /// The area of the shape /// public float Area { get; internal set; } /// /// The position of the shape's centroid relative to the shape's origin. /// public Vector2 Centroid { get; internal set; } /// /// The rotational inertia of the shape about the local origin. /// public float Inertia { get; internal set; } /// /// The mass of the shape, usually in kilograms. /// public float Mass { get; internal set; } /// /// The equal operator /// /// /// /// public static bool operator ==(MassData left, MassData right) { return (left.Area == right.Area && left.Mass == right.Mass && left.Centroid == right.Centroid && left.Inertia == right.Inertia); } /// /// The not equal operator /// /// /// /// public static bool operator !=(MassData left, MassData right) { return !(left == right); } public bool Equals(MassData other) { return this == other; } public override bool Equals(object obj) { if (ReferenceEquals(null, obj)) return false; if (obj.GetType() != typeof(MassData)) return false; return Equals((MassData)obj); } public override int GetHashCode() { unchecked { int result = Area.GetHashCode(); result = (result * 397) ^ Centroid.GetHashCode(); result = (result * 397) ^ Inertia.GetHashCode(); result = (result * 397) ^ Mass.GetHashCode(); return result; } } } public enum ShapeType { Unknown = -1, Circle = 0, Edge = 1, Polygon = 2, Chain = 3, TypeCount = 4, } /// /// A shape is used for collision detection. You can create a shape however you like. /// Shapes used for simulation in World are created automatically when a Fixture /// is created. Shapes may encapsulate a one or more child shapes. /// public abstract class Shape { internal float _density; internal float _radius; internal float _2radius; protected Shape(float density) { _density = density; ShapeType = ShapeType.Unknown; } /// /// Contains the properties of the shape such as: /// - Area of the shape /// - Centroid /// - Inertia /// - Mass /// public MassData MassData; /// /// Get the type of this shape. /// /// The type of the shape. public ShapeType ShapeType { get; internal set; } /// /// Get the number of child primitives. /// /// public abstract int ChildCount { get; } /// /// Gets or sets the density. /// Changing the density causes a recalculation of shape properties. /// /// The density. public float Density { get { return _density; } set { Debug.Assert(value >= 0); _density = value; ComputeProperties(); } } /// /// Radius of the Shape /// Changing the radius causes a recalculation of shape properties. /// public float Radius { get { return _radius; } set { Debug.Assert(value >= 0); _radius = value; _2radius = _radius * _radius; ComputeProperties(); } } /// /// Clone the concrete shape /// /// A clone of the shape public abstract Shape Clone(); /// /// Test a point for containment in this shape. /// Note: This only works for convex shapes. /// /// The shape world transform. /// A point in world coordinates. /// True if the point is inside the shape public abstract bool TestPoint(ref Transform transform, ref Vector2 point); /// /// 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 abstract bool RayCast(out RayCastOutput output, ref RayCastInput input, ref Transform transform, int childIndex); /// /// 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 abstract void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex); /// /// Compute the mass properties of this shape using its dimensions and density. /// The inertia tensor is computed about the local origin, not the centroid. /// protected abstract void ComputeProperties(); /// /// Compare this shape to another shape based on type and properties. /// /// The other shape /// True if the two shapes are the same. public bool CompareTo(Shape shape) { if (shape is PolygonShape && this is PolygonShape) return ((PolygonShape)this).CompareTo((PolygonShape)shape); if (shape is CircleShape && this is CircleShape) return ((CircleShape)this).CompareTo((CircleShape)shape); if (shape is EdgeShape && this is EdgeShape) return ((EdgeShape)this).CompareTo((EdgeShape)shape); if (shape is ChainShape && this is ChainShape) return ((ChainShape)this).CompareTo((ChainShape)shape); return false; } /// /// Used for the buoyancy controller /// public abstract float ComputeSubmergedArea(ref Vector2 normal, float offset, ref Transform xf, out Vector2 sc); } }