Fixture.cs 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  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. using System;
  23. using System.Diagnostics;
  24. using Microsoft.Xna.Framework;
  25. namespace Box2D.XNA
  26. {
  27. /// This holds contact filtering data.
  28. public struct Filter
  29. {
  30. /// The collision category bits. Normally you would just set one bit.
  31. public UInt16 categoryBits;
  32. /// The collision mask bits. This states the categories that this
  33. /// Shape would accept for collision.
  34. public UInt16 maskBits;
  35. /// Collision groups allow a certain group of objects to never collide (negative)
  36. /// or always collide (positive). Zero means no collision group. Non-zero group
  37. /// filtering always wins against the mask bits.
  38. public Int16 groupIndex;
  39. };
  40. /// A fixture definition is used to create a fixture. This class defines an
  41. /// abstract fixture definition. You can reuse fixture definitions safely.
  42. public class FixtureDef
  43. {
  44. /// The constructor sets the default fixture definition values.
  45. public FixtureDef()
  46. {
  47. shape = null;
  48. userData = null;
  49. friction = 0.2f;
  50. restitution = 0.0f;
  51. density = 0.0f;
  52. filter.categoryBits = 0x0001;
  53. filter.maskBits = 0xFFFF;
  54. filter.groupIndex = 0;
  55. isSensor = false;
  56. }
  57. /// The Shape, this must be set. The Shape will be cloned, so you
  58. /// can create the Shape on the stack.
  59. public Shape shape;
  60. /// Use this to store application specific fixture data.
  61. public object userData;
  62. /// The friction coefficient, usually in the range [0,1].
  63. public float friction;
  64. /// The restitution (elasticity) usually in the range [0,1].
  65. public float restitution;
  66. /// The density, usually in kg/m^2.
  67. public float density;
  68. /// A sensor Shape collects contact information but never generates a collision
  69. /// response.
  70. public bool isSensor;
  71. /// Contact filtering data.
  72. public Filter filter;
  73. };
  74. /// This proxy is used internally to connect fixtures to the broad-phase.
  75. public class FixtureProxy
  76. {
  77. public AABB aabb;
  78. public Fixture fixture;
  79. public int childIndex;
  80. public int proxyId;
  81. };
  82. /// A fixture is used to attach a Shape to a body for collision detection. A fixture
  83. /// inherits its transform from its parent. Fixtures hold additional non-geometric data
  84. /// such as friction, collision filters, etc.
  85. /// Fixtures are created via Body.CreateFixture.
  86. /// @warning you cannot reuse fixtures.
  87. public class Fixture
  88. {
  89. /// Get the type of the child Shape. You can use this to down cast to the concrete Shape.
  90. /// @return the Shape type.
  91. public ShapeType ShapeType
  92. {
  93. get { return _shape.ShapeType; }
  94. }
  95. /// Get the child Shape. You can modify the child Shape, however you should not change the
  96. /// number of vertices because this will crash some collision caching mechanisms.
  97. public Shape GetShape()
  98. {
  99. return _shape;
  100. }
  101. /// Is this fixture a sensor (non-solid)?
  102. /// @return the true if the Shape is a sensor.
  103. public bool IsSensor()
  104. {
  105. return _isSensor;
  106. }
  107. /// Set if this fixture is a sensor.
  108. public void SetSensor(bool sensor)
  109. {
  110. _isSensor = sensor;
  111. }
  112. /// Set the contact filtering data. This will not update contacts until the next time
  113. /// step when either parent body is active and awake.
  114. public void SetFilterData(ref Filter filter)
  115. {
  116. _filter = filter;
  117. if (_body == null)
  118. {
  119. return;
  120. }
  121. // Flag associated contacts for filtering.
  122. ContactEdge edge = _body.GetContactList();
  123. while (edge != null)
  124. {
  125. Contact contact = edge.Contact;
  126. Fixture fixtureA = contact.GetFixtureA();
  127. Fixture fixtureB = contact.GetFixtureB();
  128. if (fixtureA == this || fixtureB == this)
  129. {
  130. contact.FlagForFiltering();
  131. }
  132. edge = edge.Next;
  133. }
  134. }
  135. /// Get the contact filtering data.
  136. public void GetFilterData(out Filter filter)
  137. {
  138. filter = _filter;
  139. }
  140. /// Get the parent body of this fixture. This is null if the fixture is not attached.
  141. /// @return the parent body.
  142. public Body GetBody()
  143. {
  144. return _body;
  145. }
  146. /// Get the next fixture in the parent body's fixture list.
  147. /// @return the next Shape.
  148. public Fixture GetNext()
  149. {
  150. return _next;
  151. }
  152. /// Get the user data that was assigned in the fixture definition. Use this to
  153. /// store your application specific data.
  154. public object GetUserData()
  155. {
  156. return _userData;
  157. }
  158. /// Set the user data. Use this to store your application specific data.
  159. public void SetUserData(object data)
  160. {
  161. _userData = data;
  162. }
  163. public void SetDensity(float density)
  164. {
  165. Debug.Assert(MathUtils.IsValid(density) && density >= 0.0f);
  166. _density = density;
  167. }
  168. public float GetDensity()
  169. {
  170. return _density;
  171. }
  172. /// Test a point for containment in this fixture.
  173. /// @param xf the Shape world transform.
  174. /// @param p a point in world coordinates.
  175. public bool TestPoint(Vector2 p)
  176. {
  177. Transform xf;
  178. _body.GetTransform(out xf);
  179. return _shape.TestPoint(ref xf, p);
  180. }
  181. /// Cast a ray against this Shape.
  182. /// @param output the ray-cast results.
  183. /// @param input the ray-cast input parameters.
  184. public bool RayCast(out RayCastOutput output, ref RayCastInput input, int childIndex)
  185. {
  186. Transform xf;
  187. _body.GetTransform(out xf);
  188. return _shape.RayCast(out output, ref input, ref xf, childIndex);
  189. }
  190. /// Get the mass data for this fixture. The mass data is based on the density and
  191. /// the Shape. The rotational inertia is about the Shape's origin.
  192. public void GetMassData(out MassData massData)
  193. {
  194. _shape.ComputeMass(out massData, _density);
  195. }
  196. /// Get the coefficient of friction.
  197. public float GetFriction()
  198. {
  199. return _friction;
  200. }
  201. /// Set the coefficient of friction.
  202. public void SetFriction(float friction)
  203. {
  204. _friction = friction;
  205. }
  206. /// Get the coefficient of restitution.
  207. public float GetRestitution()
  208. {
  209. return _restitution;
  210. }
  211. /// Set the coefficient of restitution.
  212. public void SetRestitution(float restitution)
  213. {
  214. _restitution = restitution;
  215. }
  216. /// Get the fixture's AABB. This AABB may be enlarge and/or stale.
  217. /// If you need a more accurate AABB, compute it using the Shape and
  218. /// the body transform.
  219. public void GetAABB(out AABB aabb, int childIndex)
  220. {
  221. Debug.Assert(0 <= childIndex && childIndex < _proxyCount);
  222. aabb = _proxies[childIndex].aabb;
  223. }
  224. internal Fixture()
  225. {
  226. _userData = null;
  227. _body = null;
  228. _next = null;
  229. _proxyId = BroadPhase.NullProxy;
  230. _shape = null;
  231. }
  232. // We need separation create/destroy functions from the constructor/destructor because
  233. // the destructor cannot access the allocator or broad-phase (no destructor arguments allowed by C++).
  234. internal void Create(Body body, FixtureDef def)
  235. {
  236. _userData = def.userData;
  237. _friction = def.friction;
  238. _restitution = def.restitution;
  239. _body = body;
  240. _next = null;
  241. _filter = def.filter;
  242. _isSensor = def.isSensor;
  243. _shape = def.shape.Clone();
  244. // Reserve proxy space
  245. int childCount = _shape.GetChildCount();
  246. _proxies = new FixtureProxy[childCount];
  247. for (int i = 0; i < childCount; ++i)
  248. {
  249. _proxies[i] = new FixtureProxy();
  250. _proxies[i].fixture = null;
  251. _proxies[i].proxyId = BroadPhase.NullProxy;
  252. }
  253. _proxyCount = 0;
  254. _density = def.density;
  255. }
  256. internal void Destroy()
  257. {
  258. // The proxies must be destroyed before calling this.
  259. Debug.Assert(_proxyCount == 0);
  260. // Free the proxy array.
  261. _proxies = null;
  262. _shape = null;
  263. }
  264. // These support body activation/deactivation.
  265. internal void CreateProxies(BroadPhase broadPhase, ref Transform xf)
  266. {
  267. Debug.Assert(_proxyCount == 0);
  268. // Create proxies in the broad-phase.
  269. _proxyCount = _shape.GetChildCount();
  270. for (int i = 0; i < _proxyCount; ++i)
  271. {
  272. FixtureProxy proxy = _proxies[i];
  273. _shape.ComputeAABB(out proxy.aabb, ref xf, i);
  274. proxy.fixture = this;
  275. proxy.childIndex = i;
  276. proxy.proxyId = broadPhase.CreateProxy(ref proxy.aabb, proxy);
  277. _proxies[i] = proxy;
  278. }
  279. }
  280. internal void DestroyProxies(BroadPhase broadPhase)
  281. {
  282. // Destroy proxies in the broad-phase.
  283. for (int i = 0; i < _proxyCount; ++i)
  284. {
  285. broadPhase.DestroyProxy(_proxies[i].proxyId);
  286. _proxies[i].proxyId = BroadPhase.NullProxy;
  287. }
  288. _proxyCount = 0;
  289. }
  290. internal void Synchronize(BroadPhase broadPhase, ref Transform transform1, ref Transform transform2)
  291. {
  292. if (_proxyCount == 0)
  293. {
  294. return;
  295. }
  296. for (int i = 0; i < _proxyCount; ++i)
  297. {
  298. FixtureProxy proxy = _proxies[i];
  299. // Compute an AABB that covers the swept Shape (may miss some rotation effect).
  300. AABB aabb1, aabb2;
  301. _shape.ComputeAABB(out aabb1, ref transform1, proxy.childIndex);
  302. _shape.ComputeAABB(out aabb2, ref transform2, proxy.childIndex);
  303. proxy.aabb.Combine(ref aabb1, ref aabb2);
  304. Vector2 displacement = transform2.Position - transform1.Position;
  305. broadPhase.MoveProxy(proxy.proxyId, ref proxy.aabb, displacement);
  306. }
  307. }
  308. internal AABB _aabb;
  309. internal FixtureProxy[] _proxies;
  310. internal int _proxyCount;
  311. internal float _density;
  312. internal Fixture _next;
  313. internal Body _body;
  314. internal Shape _shape;
  315. internal float _friction;
  316. internal float _restitution;
  317. internal int _proxyId;
  318. internal Filter _filter;
  319. internal bool _isSensor;
  320. internal object _userData;
  321. };
  322. }