Shape.cs 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. /*
  2. * Farseer Physics Engine based on Box2D.XNA port:
  3. * Copyright (c) 2010 Ian Qvist
  4. *
  5. * Box2D.XNA port of Box2D:
  6. * Copyright (c) 2009 Brandon Furtwangler, Nathan Furtwangler
  7. *
  8. * Original source Box2D:
  9. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  10. *
  11. * This software is provided 'as-is', without any express or implied
  12. * warranty. In no event will the authors be held liable for any damages
  13. * arising from the use of this software.
  14. * Permission is granted to anyone to use this software for any purpose,
  15. * including commercial applications, and to alter it and redistribute it
  16. * freely, subject to the following restrictions:
  17. * 1. The origin of this software must not be misrepresented; you must not
  18. * claim that you wrote the original software. If you use this software
  19. * in a product, an acknowledgment in the product documentation would be
  20. * appreciated but is not required.
  21. * 2. Altered source versions must be plainly marked as such, and must not be
  22. * misrepresented as being the original software.
  23. * 3. This notice may not be removed or altered from any source distribution.
  24. */
  25. using System;
  26. using FarseerPhysics.Common;
  27. using Microsoft.Xna.Framework;
  28. namespace FarseerPhysics.Collision.Shapes
  29. {
  30. /// <summary>
  31. /// This holds the mass data computed for a shape.
  32. /// </summary>
  33. public struct MassData : IEquatable<MassData>
  34. {
  35. /// <summary>
  36. /// The area of the shape
  37. /// </summary>
  38. public float Area;
  39. /// <summary>
  40. /// The position of the shape's centroid relative to the shape's origin.
  41. /// </summary>
  42. public Vector2 Centroid;
  43. /// <summary>
  44. /// The rotational inertia of the shape about the local origin.
  45. /// </summary>
  46. public float Inertia;
  47. /// <summary>
  48. /// The mass of the shape, usually in kilograms.
  49. /// </summary>
  50. public float Mass;
  51. #region IEquatable<MassData> Members
  52. public bool Equals(MassData other)
  53. {
  54. return this == other;
  55. }
  56. #endregion
  57. public static bool operator ==(MassData left, MassData right)
  58. {
  59. return (left.Area == right.Area && left.Mass == right.Mass && left.Centroid == right.Centroid &&
  60. left.Inertia == right.Inertia);
  61. }
  62. public static bool operator !=(MassData left, MassData right)
  63. {
  64. return !(left == right);
  65. }
  66. public override bool Equals(object obj)
  67. {
  68. if (ReferenceEquals(null, obj)) return false;
  69. if (obj.GetType() != typeof(MassData)) return false;
  70. return Equals((MassData)obj);
  71. }
  72. public override int GetHashCode()
  73. {
  74. unchecked
  75. {
  76. int result = Area.GetHashCode();
  77. result = (result * 397) ^ Centroid.GetHashCode();
  78. result = (result * 397) ^ Inertia.GetHashCode();
  79. result = (result * 397) ^ Mass.GetHashCode();
  80. return result;
  81. }
  82. }
  83. }
  84. public enum ShapeType
  85. {
  86. Unknown = -1,
  87. Circle = 0,
  88. Edge = 1,
  89. Polygon = 2,
  90. Loop = 3,
  91. TypeCount = 4,
  92. }
  93. /// <summary>
  94. /// A shape is used for collision detection. You can create a shape however you like.
  95. /// Shapes used for simulation in World are created automatically when a Fixture
  96. /// is created. Shapes may encapsulate a one or more child shapes.
  97. /// </summary>
  98. public abstract class Shape
  99. {
  100. private static int _shapeIdCounter;
  101. public MassData MassData;
  102. public int ShapeId;
  103. internal float _density;
  104. internal float _radius;
  105. protected Shape(float density)
  106. {
  107. _density = density;
  108. ShapeType = ShapeType.Unknown;
  109. ShapeId = _shapeIdCounter++;
  110. }
  111. /// <summary>
  112. /// Get the type of this shape.
  113. /// </summary>
  114. /// <value>The type of the shape.</value>
  115. public ShapeType ShapeType { get; internal set; }
  116. /// <summary>
  117. /// Get the number of child primitives.
  118. /// </summary>
  119. /// <value></value>
  120. public abstract int ChildCount { get; }
  121. /// <summary>
  122. /// Gets or sets the density.
  123. /// </summary>
  124. /// <value>The density.</value>
  125. public float Density
  126. {
  127. get { return _density; }
  128. set
  129. {
  130. _density = value;
  131. ComputeProperties();
  132. }
  133. }
  134. /// <summary>
  135. /// Radius of the Shape
  136. /// </summary>
  137. public float Radius
  138. {
  139. get { return _radius; }
  140. set
  141. {
  142. _radius = value;
  143. ComputeProperties();
  144. }
  145. }
  146. /// <summary>
  147. /// Clone the concrete shape
  148. /// </summary>
  149. /// <returns>A clone of the shape</returns>
  150. public abstract Shape Clone();
  151. /// <summary>
  152. /// Test a point for containment in this shape. This only works for convex shapes.
  153. /// </summary>
  154. /// <param name="transform">The shape world transform.</param>
  155. /// <param name="point">a point in world coordinates.</param>
  156. /// <returns>True if the point is inside the shape</returns>
  157. public abstract bool TestPoint(ref Transform transform, ref Vector2 point);
  158. /// <summary>
  159. /// Cast a ray against a child shape.
  160. /// </summary>
  161. /// <param name="output">The ray-cast results.</param>
  162. /// <param name="input">The ray-cast input parameters.</param>
  163. /// <param name="transform">The transform to be applied to the shape.</param>
  164. /// <param name="childIndex">The child shape index.</param>
  165. /// <returns>True if the ray-cast hits the shape</returns>
  166. public abstract bool RayCast(out RayCastOutput output, ref RayCastInput input, ref Transform transform,
  167. int childIndex);
  168. /// <summary>
  169. /// Given a transform, compute the associated axis aligned bounding box for a child shape.
  170. /// </summary>
  171. /// <param name="aabb">The aabb results.</param>
  172. /// <param name="transform">The world transform of the shape.</param>
  173. /// <param name="childIndex">The child shape index.</param>
  174. public abstract void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex);
  175. /// <summary>
  176. /// Compute the mass properties of this shape using its dimensions and density.
  177. /// The inertia tensor is computed about the local origin, not the centroid.
  178. /// </summary>
  179. public abstract void ComputeProperties();
  180. public bool CompareTo(Shape shape)
  181. {
  182. if (shape is PolygonShape && this is PolygonShape)
  183. return ((PolygonShape)this).CompareTo((PolygonShape)shape);
  184. if (shape is CircleShape && this is CircleShape)
  185. return ((CircleShape)this).CompareTo((CircleShape)shape);
  186. if (shape is EdgeShape && this is EdgeShape)
  187. return ((EdgeShape)this).CompareTo((EdgeShape)shape);
  188. return false;
  189. }
  190. public abstract float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 sc);
  191. }
  192. }