EdgeShape.cs 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  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 FarseerPhysics.Common;
  26. using Microsoft.Xna.Framework;
  27. namespace FarseerPhysics.Collision.Shapes
  28. {
  29. /// <summary>
  30. /// A line segment (edge) Shape. These can be connected in chains or loops
  31. /// to other edge Shapes. The connectivity information is used to ensure
  32. /// correct contact normals.
  33. /// </summary>
  34. public class EdgeShape : Shape
  35. {
  36. public bool HasVertex0, HasVertex3;
  37. /// <summary>
  38. /// Optional adjacent vertices. These are used for smooth collision.
  39. /// </summary>
  40. public Vector2 Vertex0;
  41. /// <summary>
  42. /// Optional adjacent vertices. These are used for smooth collision.
  43. /// </summary>
  44. public Vector2 Vertex3;
  45. /// <summary>
  46. /// Edge start vertex
  47. /// </summary>
  48. private Vector2 _vertex1;
  49. /// <summary>
  50. /// Edge end vertex
  51. /// </summary>
  52. private Vector2 _vertex2;
  53. internal EdgeShape()
  54. : base(0)
  55. {
  56. ShapeType = ShapeType.Edge;
  57. _radius = Settings.PolygonRadius;
  58. }
  59. public EdgeShape(Vector2 start, Vector2 end)
  60. : base(0)
  61. {
  62. ShapeType = ShapeType.Edge;
  63. _radius = Settings.PolygonRadius;
  64. Set(start, end);
  65. }
  66. public override int ChildCount
  67. {
  68. get { return 1; }
  69. }
  70. /// <summary>
  71. /// These are the edge vertices
  72. /// </summary>
  73. public Vector2 Vertex1
  74. {
  75. get { return _vertex1; }
  76. set
  77. {
  78. _vertex1 = value;
  79. ComputeProperties();
  80. }
  81. }
  82. /// <summary>
  83. /// These are the edge vertices
  84. /// </summary>
  85. public Vector2 Vertex2
  86. {
  87. get { return _vertex2; }
  88. set
  89. {
  90. _vertex2 = value;
  91. ComputeProperties();
  92. }
  93. }
  94. /// <summary>
  95. /// Set this as an isolated edge.
  96. /// </summary>
  97. /// <param name="start">The start.</param>
  98. /// <param name="end">The end.</param>
  99. public void Set(Vector2 start, Vector2 end)
  100. {
  101. _vertex1 = start;
  102. _vertex2 = end;
  103. HasVertex0 = false;
  104. HasVertex3 = false;
  105. ComputeProperties();
  106. }
  107. public override Shape Clone()
  108. {
  109. EdgeShape edge = new EdgeShape();
  110. edge._radius = _radius;
  111. edge._density = _density;
  112. edge.HasVertex0 = HasVertex0;
  113. edge.HasVertex3 = HasVertex3;
  114. edge.Vertex0 = Vertex0;
  115. edge._vertex1 = _vertex1;
  116. edge._vertex2 = _vertex2;
  117. edge.Vertex3 = Vertex3;
  118. edge.MassData = MassData;
  119. return edge;
  120. }
  121. /// <summary>
  122. /// Test a point for containment in this shape. This only works for convex shapes.
  123. /// </summary>
  124. /// <param name="transform">The shape world transform.</param>
  125. /// <param name="point">a point in world coordinates.</param>
  126. /// <returns>True if the point is inside the shape</returns>
  127. public override bool TestPoint(ref Transform transform, ref Vector2 point)
  128. {
  129. return false;
  130. }
  131. /// <summary>
  132. /// Cast a ray against a child shape.
  133. /// </summary>
  134. /// <param name="output">The ray-cast results.</param>
  135. /// <param name="input">The ray-cast input parameters.</param>
  136. /// <param name="transform">The transform to be applied to the shape.</param>
  137. /// <param name="childIndex">The child shape index.</param>
  138. /// <returns>True if the ray-cast hits the shape</returns>
  139. public override bool RayCast(out RayCastOutput output, ref RayCastInput input,
  140. ref Transform transform, int childIndex)
  141. {
  142. // p = p1 + t * d
  143. // v = v1 + s * e
  144. // p1 + t * d = v1 + s * e
  145. // s * e - t * d = p1 - v1
  146. output = new RayCastOutput();
  147. // Put the ray into the edge's frame of reference.
  148. Vector2 p1 = MathUtils.MultiplyT(ref transform.R, input.Point1 - transform.Position);
  149. Vector2 p2 = MathUtils.MultiplyT(ref transform.R, input.Point2 - transform.Position);
  150. Vector2 d = p2 - p1;
  151. Vector2 v1 = _vertex1;
  152. Vector2 v2 = _vertex2;
  153. Vector2 e = v2 - v1;
  154. Vector2 normal = new Vector2(e.Y, -e.X);
  155. normal.Normalize();
  156. // q = p1 + t * d
  157. // dot(normal, q - v1) = 0
  158. // dot(normal, p1 - v1) + t * dot(normal, d) = 0
  159. float numerator = Vector2.Dot(normal, v1 - p1);
  160. float denominator = Vector2.Dot(normal, d);
  161. if (denominator == 0.0f)
  162. {
  163. return false;
  164. }
  165. float t = numerator / denominator;
  166. if (t < 0.0f || 1.0f < t)
  167. {
  168. return false;
  169. }
  170. Vector2 q = p1 + t * d;
  171. // q = v1 + s * r
  172. // s = dot(q - v1, r) / dot(r, r)
  173. Vector2 r = v2 - v1;
  174. float rr = Vector2.Dot(r, r);
  175. if (rr == 0.0f)
  176. {
  177. return false;
  178. }
  179. float s = Vector2.Dot(q - v1, r) / rr;
  180. if (s < 0.0f || 1.0f < s)
  181. {
  182. return false;
  183. }
  184. output.Fraction = t;
  185. if (numerator > 0.0f)
  186. {
  187. output.Normal = -normal;
  188. }
  189. else
  190. {
  191. output.Normal = normal;
  192. }
  193. return true;
  194. }
  195. /// <summary>
  196. /// Given a transform, compute the associated axis aligned bounding box for a child shape.
  197. /// </summary>
  198. /// <param name="aabb">The aabb results.</param>
  199. /// <param name="transform">The world transform of the shape.</param>
  200. /// <param name="childIndex">The child shape index.</param>
  201. public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
  202. {
  203. Vector2 v1 = MathUtils.Multiply(ref transform, _vertex1);
  204. Vector2 v2 = MathUtils.Multiply(ref transform, _vertex2);
  205. Vector2 lower = Vector2.Min(v1, v2);
  206. Vector2 upper = Vector2.Max(v1, v2);
  207. Vector2 r = new Vector2(Radius, Radius);
  208. aabb.LowerBound = lower - r;
  209. aabb.UpperBound = upper + r;
  210. }
  211. /// <summary>
  212. /// Compute the mass properties of this shape using its dimensions and density.
  213. /// The inertia tensor is computed about the local origin, not the centroid.
  214. /// </summary>
  215. public override void ComputeProperties()
  216. {
  217. MassData.Centroid = 0.5f * (_vertex1 + _vertex2);
  218. }
  219. public override float ComputeSubmergedArea(Vector2 normal, float offset, Transform xf, out Vector2 sc)
  220. {
  221. sc = Vector2.Zero;
  222. return 0;
  223. }
  224. public bool CompareTo(EdgeShape shape)
  225. {
  226. return (HasVertex0 == shape.HasVertex0 &&
  227. HasVertex3 == shape.HasVertex3 &&
  228. Vertex0 == shape.Vertex0 &&
  229. Vertex1 == shape.Vertex1 &&
  230. Vertex2 == shape.Vertex2 &&
  231. Vertex3 == shape.Vertex3);
  232. }
  233. }
  234. }