Body.cs 46 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375
  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 System.Collections.Generic;
  27. using System.Diagnostics;
  28. using FarseerPhysics.Collision;
  29. using FarseerPhysics.Collision.Shapes;
  30. using FarseerPhysics.Common;
  31. using FarseerPhysics.Common.PhysicsLogic;
  32. using FarseerPhysics.Controllers;
  33. using FarseerPhysics.Dynamics.Contacts;
  34. using FarseerPhysics.Dynamics.Joints;
  35. using Microsoft.Xna.Framework;
  36. namespace FarseerPhysics.Dynamics
  37. {
  38. /// <summary>
  39. /// The body type.
  40. /// </summary>
  41. public enum BodyType
  42. {
  43. /// <summary>
  44. /// Zero velocity, may be manually moved. Note: even static bodies have mass.
  45. /// </summary>
  46. Static,
  47. /// <summary>
  48. /// Zero mass, non-zero velocity set by user, moved by solver
  49. /// </summary>
  50. Kinematic,
  51. /// <summary>
  52. /// Positive mass, non-zero velocity determined by forces, moved by solver
  53. /// </summary>
  54. Dynamic,
  55. }
  56. [Flags]
  57. public enum BodyFlags
  58. {
  59. None = 0,
  60. Island = (1 << 0),
  61. Awake = (1 << 1),
  62. AutoSleep = (1 << 2),
  63. Bullet = (1 << 3),
  64. FixedRotation = (1 << 4),
  65. Enabled = (1 << 5),
  66. IgnoreGravity = (1 << 6),
  67. IgnoreCCD = (1 << 7),
  68. }
  69. public class Body : IDisposable
  70. {
  71. private static int _bodyIdCounter;
  72. internal float AngularVelocityInternal;
  73. public int BodyId;
  74. public ControllerFilter ControllerFilter;
  75. internal BodyFlags Flags;
  76. internal Vector2 Force;
  77. internal float InvI;
  78. internal float InvMass;
  79. internal Vector2 LinearVelocityInternal;
  80. public PhysicsLogicFilter PhysicsLogicFilter;
  81. internal float SleepTime;
  82. internal Sweep Sweep; // the swept motion for CCD
  83. internal float Torque;
  84. internal World World;
  85. internal Transform Xf; // the body origin transform
  86. private float _angularDamping;
  87. private BodyType _bodyType;
  88. private float _inertia;
  89. private float _linearDamping;
  90. private float _mass;
  91. internal Body()
  92. {
  93. FixtureList = new List<Fixture>(32);
  94. }
  95. public Body(World world)
  96. : this(world, null)
  97. {
  98. }
  99. public Body(World world, object userData)
  100. {
  101. FixtureList = new List<Fixture>(32);
  102. BodyId = _bodyIdCounter++;
  103. World = world;
  104. UserData = userData;
  105. FixedRotation = false;
  106. IsBullet = false;
  107. SleepingAllowed = true;
  108. Awake = true;
  109. BodyType = BodyType.Static;
  110. Enabled = true;
  111. Xf.R.Set(0);
  112. world.AddBody(this);
  113. }
  114. /// <summary>
  115. /// Gets the total number revolutions the body has made.
  116. /// </summary>
  117. /// <value>The revolutions.</value>
  118. public float Revolutions
  119. {
  120. get { return Rotation / (float)Math.PI; }
  121. }
  122. /// <summary>
  123. /// Gets or sets the body type.
  124. /// </summary>
  125. /// <value>The type of body.</value>
  126. public BodyType BodyType
  127. {
  128. get { return _bodyType; }
  129. set
  130. {
  131. if (_bodyType == value)
  132. {
  133. return;
  134. }
  135. _bodyType = value;
  136. ResetMassData();
  137. if (_bodyType == BodyType.Static)
  138. {
  139. LinearVelocityInternal = Vector2.Zero;
  140. AngularVelocityInternal = 0.0f;
  141. }
  142. Awake = true;
  143. Force = Vector2.Zero;
  144. Torque = 0.0f;
  145. // Since the body type changed, we need to flag contacts for filtering.
  146. for (int i = 0; i < FixtureList.Count; i++)
  147. {
  148. Fixture f = FixtureList[i];
  149. f.Refilter();
  150. }
  151. }
  152. }
  153. /// <summary>
  154. /// Get or sets the linear velocity of the center of mass.
  155. /// </summary>
  156. /// <value>The linear velocity.</value>
  157. public Vector2 LinearVelocity
  158. {
  159. set
  160. {
  161. Debug.Assert(!float.IsNaN(value.X) && !float.IsNaN(value.Y));
  162. if (_bodyType == BodyType.Static)
  163. return;
  164. if (Vector2.Dot(value, value) > 0.0f)
  165. Awake = true;
  166. LinearVelocityInternal = value;
  167. }
  168. get { return LinearVelocityInternal; }
  169. }
  170. /// <summary>
  171. /// Gets or sets the angular velocity. Radians/second.
  172. /// </summary>
  173. /// <value>The angular velocity.</value>
  174. public float AngularVelocity
  175. {
  176. set
  177. {
  178. Debug.Assert(!float.IsNaN(value));
  179. if (_bodyType == BodyType.Static)
  180. return;
  181. if (value * value > 0.0f)
  182. Awake = true;
  183. AngularVelocityInternal = value;
  184. }
  185. get { return AngularVelocityInternal; }
  186. }
  187. /// <summary>
  188. /// Gets or sets the linear damping.
  189. /// </summary>
  190. /// <value>The linear damping.</value>
  191. public float LinearDamping
  192. {
  193. get { return _linearDamping; }
  194. set
  195. {
  196. Debug.Assert(!float.IsNaN(value));
  197. _linearDamping = value;
  198. }
  199. }
  200. /// <summary>
  201. /// Gets or sets the angular damping.
  202. /// </summary>
  203. /// <value>The angular damping.</value>
  204. public float AngularDamping
  205. {
  206. get { return _angularDamping; }
  207. set
  208. {
  209. Debug.Assert(!float.IsNaN(value));
  210. _angularDamping = value;
  211. }
  212. }
  213. /// <summary>
  214. /// Gets or sets a value indicating whether this body should be included in the CCD solver.
  215. /// </summary>
  216. /// <value><c>true</c> if this instance is included in CCD; otherwise, <c>false</c>.</value>
  217. public bool IsBullet
  218. {
  219. set
  220. {
  221. if (value)
  222. {
  223. Flags |= BodyFlags.Bullet;
  224. }
  225. else
  226. {
  227. Flags &= ~BodyFlags.Bullet;
  228. }
  229. }
  230. get { return (Flags & BodyFlags.Bullet) == BodyFlags.Bullet; }
  231. }
  232. /// <summary>
  233. /// You can disable sleeping on this body. If you disable sleeping, the
  234. /// body will be woken.
  235. /// </summary>
  236. /// <value><c>true</c> if sleeping is allowed; otherwise, <c>false</c>.</value>
  237. public bool SleepingAllowed
  238. {
  239. set
  240. {
  241. if (value)
  242. {
  243. Flags |= BodyFlags.AutoSleep;
  244. }
  245. else
  246. {
  247. Flags &= ~BodyFlags.AutoSleep;
  248. Awake = true;
  249. }
  250. }
  251. get { return (Flags & BodyFlags.AutoSleep) == BodyFlags.AutoSleep; }
  252. }
  253. /// <summary>
  254. /// Set the sleep state of the body. A sleeping body has very
  255. /// low CPU cost.
  256. /// </summary>
  257. /// <value><c>true</c> if awake; otherwise, <c>false</c>.</value>
  258. public bool Awake
  259. {
  260. set
  261. {
  262. if (value)
  263. {
  264. if ((Flags & BodyFlags.Awake) == 0)
  265. {
  266. Flags |= BodyFlags.Awake;
  267. SleepTime = 0.0f;
  268. }
  269. }
  270. else
  271. {
  272. Flags &= ~BodyFlags.Awake;
  273. SleepTime = 0.0f;
  274. LinearVelocityInternal = Vector2.Zero;
  275. AngularVelocityInternal = 0.0f;
  276. Force = Vector2.Zero;
  277. Torque = 0.0f;
  278. }
  279. }
  280. get { return (Flags & BodyFlags.Awake) == BodyFlags.Awake; }
  281. }
  282. /// <summary>
  283. /// Set the active state of the body. An inactive body is not
  284. /// simulated and cannot be collided with or woken up.
  285. /// If you pass a flag of true, all fixtures will be added to the
  286. /// broad-phase.
  287. /// If you pass a flag of false, all fixtures will be removed from
  288. /// the broad-phase and all contacts will be destroyed.
  289. /// Fixtures and joints are otherwise unaffected. You may continue
  290. /// to create/destroy fixtures and joints on inactive bodies.
  291. /// Fixtures on an inactive body are implicitly inactive and will
  292. /// not participate in collisions, ray-casts, or queries.
  293. /// Joints connected to an inactive body are implicitly inactive.
  294. /// An inactive body is still owned by a b2World object and remains
  295. /// in the body list.
  296. /// </summary>
  297. /// <value><c>true</c> if active; otherwise, <c>false</c>.</value>
  298. public bool Enabled
  299. {
  300. set
  301. {
  302. if (value == Enabled)
  303. {
  304. return;
  305. }
  306. if (value)
  307. {
  308. Flags |= BodyFlags.Enabled;
  309. // Create all proxies.
  310. IBroadPhase broadPhase = World.ContactManager.BroadPhase;
  311. for (int i = 0; i < FixtureList.Count; i++)
  312. {
  313. FixtureList[i].CreateProxies(broadPhase, ref Xf);
  314. }
  315. // Contacts are created the next time step.
  316. }
  317. else
  318. {
  319. Flags &= ~BodyFlags.Enabled;
  320. // Destroy all proxies.
  321. IBroadPhase broadPhase = World.ContactManager.BroadPhase;
  322. for (int i = 0; i < FixtureList.Count; i++)
  323. {
  324. FixtureList[i].DestroyProxies(broadPhase);
  325. }
  326. // Destroy the attached contacts.
  327. ContactEdge ce = ContactList;
  328. while (ce != null)
  329. {
  330. ContactEdge ce0 = ce;
  331. ce = ce.Next;
  332. World.ContactManager.Destroy(ce0.Contact);
  333. }
  334. ContactList = null;
  335. }
  336. }
  337. get { return (Flags & BodyFlags.Enabled) == BodyFlags.Enabled; }
  338. }
  339. /// <summary>
  340. /// Set this body to have fixed rotation. This causes the mass
  341. /// to be reset.
  342. /// </summary>
  343. /// <value><c>true</c> if it has fixed rotation; otherwise, <c>false</c>.</value>
  344. public bool FixedRotation
  345. {
  346. set
  347. {
  348. if (value)
  349. {
  350. Flags |= BodyFlags.FixedRotation;
  351. }
  352. else
  353. {
  354. Flags &= ~BodyFlags.FixedRotation;
  355. }
  356. ResetMassData();
  357. }
  358. get { return (Flags & BodyFlags.FixedRotation) == BodyFlags.FixedRotation; }
  359. }
  360. /// <summary>
  361. /// Gets all the fixtures attached to this body.
  362. /// </summary>
  363. /// <value>The fixture list.</value>
  364. public List<Fixture> FixtureList { get; internal set; }
  365. /// <summary>
  366. /// Get the list of all joints attached to this body.
  367. /// </summary>
  368. /// <value>The joint list.</value>
  369. public JointEdge JointList { get; internal set; }
  370. /// <summary>
  371. /// Get the list of all contacts attached to this body.
  372. /// Warning: this list changes during the time step and you may
  373. /// miss some collisions if you don't use ContactListener.
  374. /// </summary>
  375. /// <value>The contact list.</value>
  376. public ContactEdge ContactList { get; internal set; }
  377. /// <summary>
  378. /// Set the user data. Use this to store your application specific data.
  379. /// </summary>
  380. /// <value>The user data.</value>
  381. public object UserData { get; set; }
  382. /// <summary>
  383. /// Get the world body origin position.
  384. /// </summary>
  385. /// <returns>Return the world position of the body's origin.</returns>
  386. public Vector2 Position
  387. {
  388. get { return Xf.Position; }
  389. set
  390. {
  391. Debug.Assert(!float.IsNaN(value.X) && !float.IsNaN(value.Y));
  392. SetTransform(ref value, Rotation);
  393. }
  394. }
  395. /// <summary>
  396. /// Get the angle in radians.
  397. /// </summary>
  398. /// <returns>Return the current world rotation angle in radians.</returns>
  399. public float Rotation
  400. {
  401. get { return Sweep.A; }
  402. set
  403. {
  404. Debug.Assert(!float.IsNaN(value));
  405. SetTransform(ref Xf.Position, value);
  406. }
  407. }
  408. /// <summary>
  409. /// Gets or sets a value indicating whether this body is static.
  410. /// </summary>
  411. /// <value><c>true</c> if this instance is static; otherwise, <c>false</c>.</value>
  412. public bool IsStatic
  413. {
  414. get { return _bodyType == BodyType.Static; }
  415. set
  416. {
  417. if (value)
  418. BodyType = BodyType.Static;
  419. else
  420. BodyType = BodyType.Dynamic;
  421. }
  422. }
  423. /// <summary>
  424. /// Gets or sets a value indicating whether this body ignores gravity.
  425. /// </summary>
  426. /// <value><c>true</c> if it ignores gravity; otherwise, <c>false</c>.</value>
  427. public bool IgnoreGravity
  428. {
  429. get { return (Flags & BodyFlags.IgnoreGravity) == BodyFlags.IgnoreGravity; }
  430. set
  431. {
  432. if (value)
  433. Flags |= BodyFlags.IgnoreGravity;
  434. else
  435. Flags &= ~BodyFlags.IgnoreGravity;
  436. }
  437. }
  438. /// <summary>
  439. /// Get the world position of the center of mass.
  440. /// </summary>
  441. /// <value>The world position.</value>
  442. public Vector2 WorldCenter
  443. {
  444. get { return Sweep.C; }
  445. }
  446. /// <summary>
  447. /// Get the local position of the center of mass.
  448. /// </summary>
  449. /// <value>The local position.</value>
  450. public Vector2 LocalCenter
  451. {
  452. get { return Sweep.LocalCenter; }
  453. set
  454. {
  455. if (_bodyType != BodyType.Dynamic)
  456. return;
  457. // Move center of mass.
  458. Vector2 oldCenter = Sweep.C;
  459. Sweep.LocalCenter = value;
  460. Sweep.C0 = Sweep.C = MathUtils.Multiply(ref Xf, ref Sweep.LocalCenter);
  461. // Update center of mass velocity.
  462. Vector2 a = Sweep.C - oldCenter;
  463. LinearVelocityInternal += new Vector2(-AngularVelocityInternal * a.Y, AngularVelocityInternal * a.X);
  464. }
  465. }
  466. /// <summary>
  467. /// Gets or sets the mass. Usually in kilograms (kg).
  468. /// </summary>
  469. /// <value>The mass.</value>
  470. public float Mass
  471. {
  472. get { return _mass; }
  473. set
  474. {
  475. Debug.Assert(!float.IsNaN(value));
  476. if (_bodyType != BodyType.Dynamic)
  477. return;
  478. _mass = value;
  479. if (_mass <= 0.0f)
  480. _mass = 1.0f;
  481. InvMass = 1.0f / _mass;
  482. }
  483. }
  484. /// <summary>
  485. /// Get or set the rotational inertia of the body about the local origin. usually in kg-m^2.
  486. /// </summary>
  487. /// <value>The inertia.</value>
  488. public float Inertia
  489. {
  490. get { return _inertia + Mass * Vector2.Dot(Sweep.LocalCenter, Sweep.LocalCenter); }
  491. set
  492. {
  493. Debug.Assert(!float.IsNaN(value));
  494. if (_bodyType != BodyType.Dynamic)
  495. return;
  496. if (value > 0.0f && (Flags & BodyFlags.FixedRotation) == 0)
  497. {
  498. _inertia = value - Mass * Vector2.Dot(LocalCenter, LocalCenter);
  499. Debug.Assert(_inertia > 0.0f);
  500. InvI = 1.0f / _inertia;
  501. }
  502. }
  503. }
  504. public float Restitution
  505. {
  506. get
  507. {
  508. float res = 0;
  509. for (int i = 0; i < FixtureList.Count; i++)
  510. {
  511. Fixture f = FixtureList[i];
  512. res += f.Restitution;
  513. }
  514. return res / FixtureList.Count;
  515. }
  516. set
  517. {
  518. for (int i = 0; i < FixtureList.Count; i++)
  519. {
  520. Fixture f = FixtureList[i];
  521. f.Restitution = value;
  522. }
  523. }
  524. }
  525. public float Friction
  526. {
  527. get
  528. {
  529. float res = 0;
  530. for (int i = 0; i < FixtureList.Count; i++)
  531. {
  532. Fixture f = FixtureList[i];
  533. res += f.Friction;
  534. }
  535. return res / FixtureList.Count;
  536. }
  537. set
  538. {
  539. for (int i = 0; i < FixtureList.Count; i++)
  540. {
  541. Fixture f = FixtureList[i];
  542. f.Friction = value;
  543. }
  544. }
  545. }
  546. public Category CollisionCategories
  547. {
  548. set
  549. {
  550. for (int i = 0; i < FixtureList.Count; i++)
  551. {
  552. Fixture f = FixtureList[i];
  553. f.CollisionCategories = value;
  554. }
  555. }
  556. }
  557. public Category CollidesWith
  558. {
  559. set
  560. {
  561. for (int i = 0; i < FixtureList.Count; i++)
  562. {
  563. Fixture f = FixtureList[i];
  564. f.CollidesWith = value;
  565. }
  566. }
  567. }
  568. public short CollisionGroup
  569. {
  570. set
  571. {
  572. for (int i = 0; i < FixtureList.Count; i++)
  573. {
  574. Fixture f = FixtureList[i];
  575. f.CollisionGroup = value;
  576. }
  577. }
  578. }
  579. public bool IsSensor
  580. {
  581. set
  582. {
  583. for (int i = 0; i < FixtureList.Count; i++)
  584. {
  585. Fixture f = FixtureList[i];
  586. f.IsSensor = value;
  587. }
  588. }
  589. }
  590. public bool IgnoreCCD
  591. {
  592. get { return (Flags & BodyFlags.IgnoreCCD) == BodyFlags.IgnoreCCD; }
  593. set
  594. {
  595. if (value)
  596. Flags |= BodyFlags.IgnoreCCD;
  597. else
  598. Flags &= ~BodyFlags.IgnoreCCD;
  599. }
  600. }
  601. #region IDisposable Members
  602. public bool IsDisposed { get; set; }
  603. public void Dispose()
  604. {
  605. if (!IsDisposed)
  606. {
  607. World.RemoveBody(this);
  608. IsDisposed = true;
  609. GC.SuppressFinalize(this);
  610. }
  611. }
  612. #endregion
  613. /// <summary>
  614. /// Resets the dynamics of this body.
  615. /// Sets torque, force and linear/angular velocity to 0
  616. /// </summary>
  617. public void ResetDynamics()
  618. {
  619. Torque = 0;
  620. AngularVelocityInternal = 0;
  621. Force = Vector2.Zero;
  622. LinearVelocityInternal = Vector2.Zero;
  623. }
  624. /// <summary>
  625. /// Creates a fixture and attach it to this body.
  626. /// If the density is non-zero, this function automatically updates the mass of the body.
  627. /// Contacts are not created until the next time step.
  628. /// Warning: This function is locked during callbacks.
  629. /// </summary>
  630. /// <param name="shape">The shape.</param>
  631. /// <returns></returns>
  632. public Fixture CreateFixture(Shape shape)
  633. {
  634. return new Fixture(this, shape);
  635. }
  636. /// <summary>
  637. /// Creates a fixture and attach it to this body.
  638. /// If the density is non-zero, this function automatically updates the mass of the body.
  639. /// Contacts are not created until the next time step.
  640. /// Warning: This function is locked during callbacks.
  641. /// </summary>
  642. /// <param name="shape">The shape.</param>
  643. /// <param name="userData">Application specific data</param>
  644. /// <returns></returns>
  645. public Fixture CreateFixture(Shape shape, object userData)
  646. {
  647. return new Fixture(this, shape, userData);
  648. }
  649. /// <summary>
  650. /// Destroy a fixture. This removes the fixture from the broad-phase and
  651. /// destroys all contacts associated with this fixture. This will
  652. /// automatically adjust the mass of the body if the body is dynamic and the
  653. /// fixture has positive density.
  654. /// All fixtures attached to a body are implicitly destroyed when the body is destroyed.
  655. /// Warning: This function is locked during callbacks.
  656. /// </summary>
  657. /// <param name="fixture">The fixture to be removed.</param>
  658. public void DestroyFixture(Fixture fixture)
  659. {
  660. Debug.Assert(fixture.Body == this);
  661. // Remove the fixture from this body's singly linked list.
  662. Debug.Assert(FixtureList.Count > 0);
  663. // You tried to remove a fixture that not present in the fixturelist.
  664. Debug.Assert(FixtureList.Contains(fixture));
  665. // Destroy any contacts associated with the fixture.
  666. ContactEdge edge = ContactList;
  667. while (edge != null)
  668. {
  669. Contact c = edge.Contact;
  670. edge = edge.Next;
  671. Fixture fixtureA = c.FixtureA;
  672. Fixture fixtureB = c.FixtureB;
  673. if (fixture == fixtureA || fixture == fixtureB)
  674. {
  675. // This destroys the contact and removes it from
  676. // this body's contact list.
  677. World.ContactManager.Destroy(c);
  678. }
  679. }
  680. if ((Flags & BodyFlags.Enabled) == BodyFlags.Enabled)
  681. {
  682. IBroadPhase broadPhase = World.ContactManager.BroadPhase;
  683. fixture.DestroyProxies(broadPhase);
  684. }
  685. FixtureList.Remove(fixture);
  686. fixture.Destroy();
  687. fixture.Body = null;
  688. ResetMassData();
  689. }
  690. /// <summary>
  691. /// Set the position of the body's origin and rotation.
  692. /// This breaks any contacts and wakes the other bodies.
  693. /// Manipulating a body's transform may cause non-physical behavior.
  694. /// </summary>
  695. /// <param name="position">The world position of the body's local origin.</param>
  696. /// <param name="rotation">The world rotation in radians.</param>
  697. public void SetTransform(ref Vector2 position, float rotation)
  698. {
  699. SetTransformIgnoreContacts(ref position, rotation);
  700. World.ContactManager.FindNewContacts();
  701. }
  702. /// <summary>
  703. /// Set the position of the body's origin and rotation.
  704. /// This breaks any contacts and wakes the other bodies.
  705. /// Manipulating a body's transform may cause non-physical behavior.
  706. /// </summary>
  707. /// <param name="position">The world position of the body's local origin.</param>
  708. /// <param name="rotation">The world rotation in radians.</param>
  709. public void SetTransform(Vector2 position, float rotation)
  710. {
  711. SetTransform(ref position, rotation);
  712. }
  713. /// <summary>
  714. /// For teleporting a body without considering new contacts immediately.
  715. /// </summary>
  716. /// <param name="position">The position.</param>
  717. /// <param name="angle">The angle.</param>
  718. public void SetTransformIgnoreContacts(ref Vector2 position, float angle)
  719. {
  720. Xf.R.Set(angle);
  721. Xf.Position = position;
  722. Sweep.C0 =
  723. Sweep.C =
  724. new Vector2(Xf.Position.X + Xf.R.Col1.X * Sweep.LocalCenter.X + Xf.R.Col2.X * Sweep.LocalCenter.Y,
  725. Xf.Position.Y + Xf.R.Col1.Y * Sweep.LocalCenter.X + Xf.R.Col2.Y * Sweep.LocalCenter.Y);
  726. Sweep.A0 = Sweep.A = angle;
  727. IBroadPhase broadPhase = World.ContactManager.BroadPhase;
  728. for (int i = 0; i < FixtureList.Count; i++)
  729. {
  730. FixtureList[i].Synchronize(broadPhase, ref Xf, ref Xf);
  731. }
  732. }
  733. /// <summary>
  734. /// Get the body transform for the body's origin.
  735. /// </summary>
  736. /// <param name="transform">The transform of the body's origin.</param>
  737. public void GetTransform(out Transform transform)
  738. {
  739. transform = Xf;
  740. }
  741. /// <summary>
  742. /// Apply a force at a world point. If the force is not
  743. /// applied at the center of mass, it will generate a torque and
  744. /// affect the angular velocity. This wakes up the body.
  745. /// </summary>
  746. /// <param name="force">The world force vector, usually in Newtons (N).</param>
  747. /// <param name="point">The world position of the point of application.</param>
  748. public void ApplyForce(Vector2 force, Vector2 point)
  749. {
  750. ApplyForce(ref force, ref point);
  751. }
  752. /// <summary>
  753. /// Applies a force at the center of mass.
  754. /// </summary>
  755. /// <param name="force">The force.</param>
  756. public void ApplyForce(ref Vector2 force)
  757. {
  758. ApplyForce(ref force, ref Xf.Position);
  759. }
  760. /// <summary>
  761. /// Applies a force at the center of mass.
  762. /// </summary>
  763. /// <param name="force">The force.</param>
  764. public void ApplyForce(Vector2 force)
  765. {
  766. ApplyForce(ref force, ref Xf.Position);
  767. }
  768. /// <summary>
  769. /// Apply a force at a world point. If the force is not
  770. /// applied at the center of mass, it will generate a torque and
  771. /// affect the angular velocity. This wakes up the body.
  772. /// </summary>
  773. /// <param name="force">The world force vector, usually in Newtons (N).</param>
  774. /// <param name="point">The world position of the point of application.</param>
  775. public void ApplyForce(ref Vector2 force, ref Vector2 point)
  776. {
  777. Debug.Assert(!float.IsNaN(force.X));
  778. Debug.Assert(!float.IsNaN(force.Y));
  779. Debug.Assert(!float.IsNaN(point.X));
  780. Debug.Assert(!float.IsNaN(point.Y));
  781. if (_bodyType == BodyType.Dynamic)
  782. {
  783. if (Awake == false)
  784. {
  785. Awake = true;
  786. }
  787. Force += force;
  788. Torque += (point.X - Sweep.C.X) * force.Y - (point.Y - Sweep.C.Y) * force.X;
  789. }
  790. }
  791. /// <summary>
  792. /// Apply a torque. This affects the angular velocity
  793. /// without affecting the linear velocity of the center of mass.
  794. /// This wakes up the body.
  795. /// </summary>
  796. /// <param name="torque">The torque about the z-axis (out of the screen), usually in N-m.</param>
  797. public void ApplyTorque(float torque)
  798. {
  799. Debug.Assert(!float.IsNaN(torque));
  800. if (_bodyType == BodyType.Dynamic)
  801. {
  802. if (Awake == false)
  803. {
  804. Awake = true;
  805. }
  806. Torque += torque;
  807. }
  808. }
  809. /// <summary>
  810. /// Apply an impulse at a point. This immediately modifies the velocity.
  811. /// This wakes up the body.
  812. /// </summary>
  813. /// <param name="impulse">The world impulse vector, usually in N-seconds or kg-m/s.</param>
  814. public void ApplyLinearImpulse(Vector2 impulse)
  815. {
  816. ApplyLinearImpulse(ref impulse);
  817. }
  818. /// <summary>
  819. /// Apply an impulse at a point. This immediately modifies the velocity.
  820. /// It also modifies the angular velocity if the point of application
  821. /// is not at the center of mass.
  822. /// This wakes up the body.
  823. /// </summary>
  824. /// <param name="impulse">The world impulse vector, usually in N-seconds or kg-m/s.</param>
  825. /// <param name="point">The world position of the point of application.</param>
  826. public void ApplyLinearImpulse(Vector2 impulse, Vector2 point)
  827. {
  828. ApplyLinearImpulse(ref impulse, ref point);
  829. }
  830. /// <summary>
  831. /// Apply an impulse at a point. This immediately modifies the velocity.
  832. /// This wakes up the body.
  833. /// </summary>
  834. /// <param name="impulse">The world impulse vector, usually in N-seconds or kg-m/s.</param>
  835. public void ApplyLinearImpulse(ref Vector2 impulse)
  836. {
  837. if (_bodyType != BodyType.Dynamic)
  838. {
  839. return;
  840. }
  841. if (Awake == false)
  842. {
  843. Awake = true;
  844. }
  845. LinearVelocityInternal += InvMass * impulse;
  846. }
  847. /// <summary>
  848. /// Apply an impulse at a point. This immediately modifies the velocity.
  849. /// It also modifies the angular velocity if the point of application
  850. /// is not at the center of mass.
  851. /// This wakes up the body.
  852. /// </summary>
  853. /// <param name="impulse">The world impulse vector, usually in N-seconds or kg-m/s.</param>
  854. /// <param name="point">The world position of the point of application.</param>
  855. public void ApplyLinearImpulse(ref Vector2 impulse, ref Vector2 point)
  856. {
  857. if (_bodyType != BodyType.Dynamic)
  858. return;
  859. if (Awake == false)
  860. Awake = true;
  861. LinearVelocityInternal += InvMass * impulse;
  862. AngularVelocityInternal += InvI * ((point.X - Sweep.C.X) * impulse.Y - (point.Y - Sweep.C.Y) * impulse.X);
  863. }
  864. /// <summary>
  865. /// Apply an angular impulse.
  866. /// </summary>
  867. /// <param name="impulse">The angular impulse in units of kg*m*m/s.</param>
  868. public void ApplyAngularImpulse(float impulse)
  869. {
  870. if (_bodyType != BodyType.Dynamic)
  871. {
  872. return;
  873. }
  874. if (Awake == false)
  875. {
  876. Awake = true;
  877. }
  878. AngularVelocityInternal += InvI * impulse;
  879. }
  880. /// <summary>
  881. /// This resets the mass properties to the sum of the mass properties of the fixtures.
  882. /// This normally does not need to be called unless you called SetMassData to override
  883. /// the mass and you later want to reset the mass.
  884. /// </summary>
  885. public void ResetMassData()
  886. {
  887. // Compute mass data from shapes. Each shape has its own density.
  888. _mass = 0.0f;
  889. InvMass = 0.0f;
  890. _inertia = 0.0f;
  891. InvI = 0.0f;
  892. Sweep.LocalCenter = Vector2.Zero;
  893. // Kinematic bodies have zero mass.
  894. if (BodyType == BodyType.Kinematic)
  895. {
  896. Sweep.C0 = Sweep.C = Xf.Position;
  897. return;
  898. }
  899. Debug.Assert(BodyType == BodyType.Dynamic || BodyType == BodyType.Static);
  900. // Accumulate mass over all fixtures.
  901. Vector2 center = Vector2.Zero;
  902. foreach (Fixture f in FixtureList)
  903. {
  904. if (f.Shape._density == 0)
  905. {
  906. continue;
  907. }
  908. MassData massData = f.Shape.MassData;
  909. _mass += massData.Mass;
  910. center += massData.Mass * massData.Centroid;
  911. _inertia += massData.Inertia;
  912. }
  913. //Static bodies only have mass, they don't have other properties. A little hacky tho...
  914. if (BodyType == BodyType.Static)
  915. {
  916. Sweep.C0 = Sweep.C = Xf.Position;
  917. return;
  918. }
  919. // Compute center of mass.
  920. if (_mass > 0.0f)
  921. {
  922. InvMass = 1.0f / _mass;
  923. center *= InvMass;
  924. }
  925. else
  926. {
  927. // Force all dynamic bodies to have a positive mass.
  928. _mass = 1.0f;
  929. InvMass = 1.0f;
  930. }
  931. if (_inertia > 0.0f && (Flags & BodyFlags.FixedRotation) == 0)
  932. {
  933. // Center the inertia about the center of mass.
  934. _inertia -= _mass * Vector2.Dot(center, center);
  935. Debug.Assert(_inertia > 0.0f);
  936. InvI = 1.0f / _inertia;
  937. }
  938. else
  939. {
  940. _inertia = 0.0f;
  941. InvI = 0.0f;
  942. }
  943. // Move center of mass.
  944. Vector2 oldCenter = Sweep.C;
  945. Sweep.LocalCenter = center;
  946. Sweep.C0 = Sweep.C = MathUtils.Multiply(ref Xf, ref Sweep.LocalCenter);
  947. // Update center of mass velocity.
  948. Vector2 a = Sweep.C - oldCenter;
  949. LinearVelocityInternal += new Vector2(-AngularVelocityInternal * a.Y, AngularVelocityInternal * a.X);
  950. }
  951. /// <summary>
  952. /// Get the world coordinates of a point given the local coordinates.
  953. /// </summary>
  954. /// <param name="localPoint">A point on the body measured relative the the body's origin.</param>
  955. /// <returns>The same point expressed in world coordinates.</returns>
  956. public Vector2 GetWorldPoint(ref Vector2 localPoint)
  957. {
  958. return new Vector2(Xf.Position.X + Xf.R.Col1.X * localPoint.X + Xf.R.Col2.X * localPoint.Y,
  959. Xf.Position.Y + Xf.R.Col1.Y * localPoint.X + Xf.R.Col2.Y * localPoint.Y);
  960. }
  961. /// <summary>
  962. /// Get the world coordinates of a point given the local coordinates.
  963. /// </summary>
  964. /// <param name="localPoint">A point on the body measured relative the the body's origin.</param>
  965. /// <returns>The same point expressed in world coordinates.</returns>
  966. public Vector2 GetWorldPoint(Vector2 localPoint)
  967. {
  968. return GetWorldPoint(ref localPoint);
  969. }
  970. /// <summary>
  971. /// Get the world coordinates of a vector given the local coordinates.
  972. /// Note that the vector only takes the rotation into account, not the position.
  973. /// </summary>
  974. /// <param name="localVector">A vector fixed in the body.</param>
  975. /// <returns>The same vector expressed in world coordinates.</returns>
  976. public Vector2 GetWorldVector(ref Vector2 localVector)
  977. {
  978. return new Vector2(Xf.R.Col1.X * localVector.X + Xf.R.Col2.X * localVector.Y,
  979. Xf.R.Col1.Y * localVector.X + Xf.R.Col2.Y * localVector.Y);
  980. }
  981. /// <summary>
  982. /// Get the world coordinates of a vector given the local coordinates.
  983. /// </summary>
  984. /// <param name="localVector">A vector fixed in the body.</param>
  985. /// <returns>The same vector expressed in world coordinates.</returns>
  986. public Vector2 GetWorldVector(Vector2 localVector)
  987. {
  988. return GetWorldVector(ref localVector);
  989. }
  990. /// <summary>
  991. /// Gets a local point relative to the body's origin given a world point.
  992. /// Note that the vector only takes the rotation into account, not the position.
  993. /// </summary>
  994. /// <param name="worldPoint">A point in world coordinates.</param>
  995. /// <returns>The corresponding local point relative to the body's origin.</returns>
  996. public Vector2 GetLocalPoint(ref Vector2 worldPoint)
  997. {
  998. return
  999. new Vector2((worldPoint.X - Xf.Position.X) * Xf.R.Col1.X + (worldPoint.Y - Xf.Position.Y) * Xf.R.Col1.Y,
  1000. (worldPoint.X - Xf.Position.X) * Xf.R.Col2.X + (worldPoint.Y - Xf.Position.Y) * Xf.R.Col2.Y);
  1001. }
  1002. /// <summary>
  1003. /// Gets a local point relative to the body's origin given a world point.
  1004. /// </summary>
  1005. /// <param name="worldPoint">A point in world coordinates.</param>
  1006. /// <returns>The corresponding local point relative to the body's origin.</returns>
  1007. public Vector2 GetLocalPoint(Vector2 worldPoint)
  1008. {
  1009. return GetLocalPoint(ref worldPoint);
  1010. }
  1011. /// <summary>
  1012. /// Gets a local vector given a world vector.
  1013. /// Note that the vector only takes the rotation into account, not the position.
  1014. /// </summary>
  1015. /// <param name="worldVector">A vector in world coordinates.</param>
  1016. /// <returns>The corresponding local vector.</returns>
  1017. public Vector2 GetLocalVector(ref Vector2 worldVector)
  1018. {
  1019. return new Vector2(worldVector.X * Xf.R.Col1.X + worldVector.Y * Xf.R.Col1.Y,
  1020. worldVector.X * Xf.R.Col2.X + worldVector.Y * Xf.R.Col2.Y);
  1021. }
  1022. /// <summary>
  1023. /// Gets a local vector given a world vector.
  1024. /// Note that the vector only takes the rotation into account, not the position.
  1025. /// </summary>
  1026. /// <param name="worldVector">A vector in world coordinates.</param>
  1027. /// <returns>The corresponding local vector.</returns>
  1028. public Vector2 GetLocalVector(Vector2 worldVector)
  1029. {
  1030. return GetLocalVector(ref worldVector);
  1031. }
  1032. /// <summary>
  1033. /// Get the world linear velocity of a world point attached to this body.
  1034. /// </summary>
  1035. /// <param name="worldPoint">A point in world coordinates.</param>
  1036. /// <returns>The world velocity of a point.</returns>
  1037. public Vector2 GetLinearVelocityFromWorldPoint(Vector2 worldPoint)
  1038. {
  1039. return GetLinearVelocityFromWorldPoint(ref worldPoint);
  1040. }
  1041. /// <summary>
  1042. /// Get the world linear velocity of a world point attached to this body.
  1043. /// </summary>
  1044. /// <param name="worldPoint">A point in world coordinates.</param>
  1045. /// <returns>The world velocity of a point.</returns>
  1046. public Vector2 GetLinearVelocityFromWorldPoint(ref Vector2 worldPoint)
  1047. {
  1048. return LinearVelocityInternal +
  1049. new Vector2(-AngularVelocityInternal * (worldPoint.Y - Sweep.C.Y),
  1050. AngularVelocityInternal * (worldPoint.X - Sweep.C.X));
  1051. }
  1052. /// <summary>
  1053. /// Get the world velocity of a local point.
  1054. /// </summary>
  1055. /// <param name="localPoint">A point in local coordinates.</param>
  1056. /// <returns>The world velocity of a point.</returns>
  1057. public Vector2 GetLinearVelocityFromLocalPoint(Vector2 localPoint)
  1058. {
  1059. return GetLinearVelocityFromLocalPoint(ref localPoint);
  1060. }
  1061. /// <summary>
  1062. /// Get the world velocity of a local point.
  1063. /// </summary>
  1064. /// <param name="localPoint">A point in local coordinates.</param>
  1065. /// <returns>The world velocity of a point.</returns>
  1066. public Vector2 GetLinearVelocityFromLocalPoint(ref Vector2 localPoint)
  1067. {
  1068. return GetLinearVelocityFromWorldPoint(GetWorldPoint(ref localPoint));
  1069. }
  1070. public Body DeepClone()
  1071. {
  1072. Body body = Clone();
  1073. for (int i = 0; i < FixtureList.Count; i++)
  1074. {
  1075. FixtureList[i].Clone(body);
  1076. }
  1077. return body;
  1078. }
  1079. public Body Clone()
  1080. {
  1081. Body body = new Body();
  1082. body.World = World;
  1083. body.UserData = UserData;
  1084. body.LinearDamping = LinearDamping;
  1085. body.LinearVelocityInternal = LinearVelocityInternal;
  1086. body.AngularDamping = AngularDamping;
  1087. body.AngularVelocityInternal = AngularVelocityInternal;
  1088. body.Position = Position;
  1089. body.Rotation = Rotation;
  1090. body._bodyType = _bodyType;
  1091. body.Flags = Flags;
  1092. World.AddBody(body);
  1093. return body;
  1094. }
  1095. internal void SynchronizeFixtures()
  1096. {
  1097. Transform xf1 = new Transform();
  1098. float c = (float)Math.Cos(Sweep.A0), s = (float)Math.Sin(Sweep.A0);
  1099. xf1.R.Col1.X = c;
  1100. xf1.R.Col2.X = -s;
  1101. xf1.R.Col1.Y = s;
  1102. xf1.R.Col2.Y = c;
  1103. xf1.Position.X = Sweep.C0.X - (xf1.R.Col1.X * Sweep.LocalCenter.X + xf1.R.Col2.X * Sweep.LocalCenter.Y);
  1104. xf1.Position.Y = Sweep.C0.Y - (xf1.R.Col1.Y * Sweep.LocalCenter.X + xf1.R.Col2.Y * Sweep.LocalCenter.Y);
  1105. IBroadPhase broadPhase = World.ContactManager.BroadPhase;
  1106. for (int i = 0; i < FixtureList.Count; i++)
  1107. {
  1108. FixtureList[i].Synchronize(broadPhase, ref xf1, ref Xf);
  1109. }
  1110. }
  1111. internal void SynchronizeTransform()
  1112. {
  1113. Xf.R.Set(Sweep.A);
  1114. float vx = Xf.R.Col1.X * Sweep.LocalCenter.X + Xf.R.Col2.X * Sweep.LocalCenter.Y;
  1115. float vy = Xf.R.Col1.Y * Sweep.LocalCenter.X + Xf.R.Col2.Y * Sweep.LocalCenter.Y;
  1116. Xf.Position.X = Sweep.C.X - vx;
  1117. Xf.Position.Y = Sweep.C.Y - vy;
  1118. }
  1119. /// <summary>
  1120. /// This is used to prevent connected bodies from colliding.
  1121. /// It may lie, depending on the collideConnected flag.
  1122. /// </summary>
  1123. /// <param name="other">The other body.</param>
  1124. /// <returns></returns>
  1125. internal bool ShouldCollide(Body other)
  1126. {
  1127. // At least one body should be dynamic.
  1128. if (_bodyType != BodyType.Dynamic && other._bodyType != BodyType.Dynamic)
  1129. {
  1130. return false;
  1131. }
  1132. // Does a joint prevent collision?
  1133. for (JointEdge jn = JointList; jn != null; jn = jn.Next)
  1134. {
  1135. if (jn.Other == other)
  1136. {
  1137. if (jn.Joint.CollideConnected == false)
  1138. {
  1139. return false;
  1140. }
  1141. }
  1142. }
  1143. return true;
  1144. }
  1145. internal void Advance(float alpha)
  1146. {
  1147. // Advance to the new safe time.
  1148. Sweep.Advance(alpha);
  1149. Sweep.C = Sweep.C0;
  1150. Sweep.A = Sweep.A0;
  1151. SynchronizeTransform();
  1152. }
  1153. public event OnCollisionEventHandler OnCollision
  1154. {
  1155. add
  1156. {
  1157. for (int i = 0; i < FixtureList.Count; i++)
  1158. {
  1159. FixtureList[i].OnCollision += value;
  1160. }
  1161. }
  1162. remove
  1163. {
  1164. for (int i = 0; i < FixtureList.Count; i++)
  1165. {
  1166. FixtureList[i].OnCollision -= value;
  1167. }
  1168. }
  1169. }
  1170. public event OnSeparationEventHandler OnSeparation
  1171. {
  1172. add
  1173. {
  1174. for (int i = 0; i < FixtureList.Count; i++)
  1175. {
  1176. FixtureList[i].OnSeparation += value;
  1177. }
  1178. }
  1179. remove
  1180. {
  1181. for (int i = 0; i < FixtureList.Count; i++)
  1182. {
  1183. FixtureList[i].OnSeparation -= value;
  1184. }
  1185. }
  1186. }
  1187. public void IgnoreCollisionWith(Body other)
  1188. {
  1189. for (int i = 0; i < FixtureList.Count; i++)
  1190. {
  1191. Fixture f = FixtureList[i];
  1192. for (int j = 0; j < other.FixtureList.Count; j++)
  1193. {
  1194. Fixture f2 = other.FixtureList[j];
  1195. f.IgnoreCollisionWith(f2);
  1196. }
  1197. }
  1198. }
  1199. public void RestoreCollisionWith(Body other)
  1200. {
  1201. for (int i = 0; i < FixtureList.Count; i++)
  1202. {
  1203. Fixture f = FixtureList[i];
  1204. for (int j = 0; j < other.FixtureList.Count; j++)
  1205. {
  1206. Fixture f2 = other.FixtureList[j];
  1207. f.RestoreCollisionWith(f2);
  1208. }
  1209. }
  1210. }
  1211. }
  1212. }