EdgeShape.cs 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. /*
  2. * Box2D.XNA port of Box2D:
  3. * Copyright (c) 2009 Brandon Furtwangler, Nathan Furtwangler
  4. *
  5. * Original source Box2D:
  6. * Copyright (c) 2006-2009 Erin Catto http://www.gphysics.com
  7. *
  8. * This software is provided 'as-is', without any express or implied
  9. * warranty. In no event will the authors be held liable for any damages
  10. * arising from the use of this software.
  11. * Permission is granted to anyone to use this software for any purpose,
  12. * including commercial applications, and to alter it and redistribute it
  13. * freely, subject to the following restrictions:
  14. * 1. The origin of this software must not be misrepresented; you must not
  15. * claim that you wrote the original software. If you use this software
  16. * in a product, an acknowledgment in the product documentation would be
  17. * appreciated but is not required.
  18. * 2. Altered source versions must be plainly marked as such, and must not be
  19. * misrepresented as being the original software.
  20. * 3. This notice may not be removed or altered from any source distribution.
  21. */
  22. /// A line segment (edge) Shape. These can be connected in chains or loops
  23. /// to other edge Shapes. The connectivity information is used to ensure
  24. /// correct contact normals.
  25. using Microsoft.Xna.Framework;
  26. namespace Box2D.XNA
  27. {
  28. public class EdgeShape : Shape
  29. {
  30. public EdgeShape()
  31. {
  32. ShapeType = ShapeType.Edge;
  33. _radius = Settings.b2_polygonRadius;
  34. _hasVertex0 = false;
  35. _hasVertex3 = false;
  36. }
  37. /// Set this as an isolated edge.
  38. public void Set(Vector2 v1, Vector2 v2)
  39. {
  40. _vertex1 = v1;
  41. _vertex2 = v2;
  42. _hasVertex0 = false;
  43. _hasVertex3 = false;
  44. }
  45. /// Implement Shape.
  46. public override Shape Clone()
  47. {
  48. var edge = new EdgeShape();
  49. edge._hasVertex0 = _hasVertex0;
  50. edge._hasVertex3 = _hasVertex3;
  51. edge._radius = _radius;
  52. edge._vertex0 = _vertex0;
  53. edge._vertex1 = _vertex1;
  54. edge._vertex2 = _vertex2;
  55. edge._vertex3 = _vertex3;
  56. return edge;
  57. }
  58. /// @see Shape::GetChildCount
  59. public override int GetChildCount()
  60. {
  61. return 1;
  62. }
  63. /// @see Shape::TestPoint
  64. public override bool TestPoint(ref Transform transform, Vector2 p)
  65. {
  66. return false;
  67. }
  68. /// Implement Shape.
  69. ///
  70. // p = p1 + t * d
  71. // v = v1 + s * e
  72. // p1 + t * d = v1 + s * e
  73. // s * e - t * d = p1 - v1
  74. //
  75. public override bool RayCast(out RayCastOutput output, ref RayCastInput input,
  76. ref Transform transform, int childIndex)
  77. {
  78. output = new RayCastOutput();
  79. // Put the ray into the edge's frame of reference.
  80. Vector2 p1 = MathUtils.MultiplyT(ref transform.R, input.p1 - transform.Position);
  81. Vector2 p2 = MathUtils.MultiplyT(ref transform.R, input.p2 - transform.Position);
  82. Vector2 d = p2 - p1;
  83. Vector2 v1 = _vertex1;
  84. Vector2 v2 = _vertex2;
  85. Vector2 e = v2 - v1;
  86. Vector2 normal = new Vector2(e.Y, -e.X);
  87. normal.Normalize();
  88. // q = p1 + t * d
  89. // dot(normal, q - v1) = 0
  90. // dot(normal, p1 - v1) + t * dot(normal, d) = 0
  91. float numerator = Vector2.Dot(normal, v1 - p1);
  92. float denominator = Vector2.Dot(normal, d);
  93. if (denominator == 0.0f)
  94. {
  95. return false;
  96. }
  97. float t = numerator / denominator;
  98. if (t < 0.0f || 1.0f < t)
  99. {
  100. return false;
  101. }
  102. Vector2 q = p1 + t * d;
  103. // q = v1 + s * r
  104. // s = dot(q - v1, r) / dot(r, r)
  105. Vector2 r = v2 - v1;
  106. float rr = Vector2.Dot(r, r);
  107. if (rr == 0.0f)
  108. {
  109. return false;
  110. }
  111. float s = Vector2.Dot(q - v1, r) / rr;
  112. if (s < 0.0f || 1.0f < s)
  113. {
  114. return false;
  115. }
  116. output.fraction = t;
  117. if (numerator > 0.0f)
  118. {
  119. output.normal = -normal;
  120. }
  121. else
  122. {
  123. output.normal = normal;
  124. }
  125. return true;
  126. }
  127. /// @see Shape::ComputeAABB
  128. public override void ComputeAABB(out AABB aabb, ref Transform transform, int childIndex)
  129. {
  130. aabb = new AABB();
  131. Vector2 v1 = MathUtils.Multiply(ref transform, _vertex1);
  132. Vector2 v2 = MathUtils.Multiply(ref transform, _vertex2);
  133. Vector2 lower = Vector2.Min(v1, v2);
  134. Vector2 upper = Vector2.Max(v1, v2);
  135. Vector2 r = new Vector2(_radius, _radius);
  136. aabb.lowerBound = lower - r;
  137. aabb.upperBound = upper + r;
  138. }
  139. /// @see Shape::ComputeMass
  140. public override void ComputeMass(out MassData massData, float density)
  141. {
  142. massData = new MassData();
  143. massData.mass = 0.0f;
  144. massData.center = 0.5f * (_vertex1 + _vertex2);
  145. massData.I = 0.0f;
  146. }
  147. /// These are the edge vertices
  148. public Vector2 _vertex1, _vertex2;
  149. /// Optional adjacent vertices. These are used for smooth collision.
  150. public Vector2 _vertex0, _vertex3;
  151. public bool _hasVertex0, _hasVertex3;
  152. }
  153. }