World.cs 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456
  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.Common;
  30. using FarseerPhysics.Controllers;
  31. using FarseerPhysics.Dynamics.Contacts;
  32. using FarseerPhysics.Dynamics.Joints;
  33. using Microsoft.Xna.Framework;
  34. namespace FarseerPhysics.Dynamics
  35. {
  36. /// <summary>
  37. /// Contains filter data that can determine whether an object should be processed or not.
  38. /// </summary>
  39. public abstract class FilterData
  40. {
  41. public Category DisabledOnCategories = Category.None;
  42. public int DisabledOnGroup;
  43. public Category EnabledOnCategories = Category.All;
  44. public int EnabledOnGroup;
  45. public virtual bool IsActiveOn(Body body)
  46. {
  47. if (body == null || !body.Enabled || body.IsStatic)
  48. return false;
  49. if (body.FixtureList == null)
  50. return false;
  51. foreach (Fixture fixture in body.FixtureList)
  52. {
  53. //Disable
  54. if ((fixture.CollisionGroup == DisabledOnGroup) &&
  55. fixture.CollisionGroup != 0 && DisabledOnGroup != 0)
  56. return false;
  57. if ((fixture.CollisionCategories & DisabledOnCategories) != Category.None)
  58. return false;
  59. if (EnabledOnGroup != 0 || EnabledOnCategories != Category.All)
  60. {
  61. //Enable
  62. if ((fixture.CollisionGroup == EnabledOnGroup) &&
  63. fixture.CollisionGroup != 0 && EnabledOnGroup != 0)
  64. return true;
  65. if ((fixture.CollisionCategories & EnabledOnCategories) != Category.None &&
  66. EnabledOnCategories != Category.All)
  67. return true;
  68. }
  69. else
  70. {
  71. return true;
  72. }
  73. }
  74. return false;
  75. }
  76. /// <summary>
  77. /// Adds the category.
  78. /// </summary>
  79. /// <param name="category">The category.</param>
  80. public void AddDisabledCategory(Category category)
  81. {
  82. DisabledOnCategories |= category;
  83. }
  84. /// <summary>
  85. /// Removes the category.
  86. /// </summary>
  87. /// <param name="category">The category.</param>
  88. public void RemoveDisabledCategory(Category category)
  89. {
  90. DisabledOnCategories &= ~category;
  91. }
  92. /// <summary>
  93. /// Determines whether this body ignores the the specified controller.
  94. /// </summary>
  95. /// <param name="category">The category.</param>
  96. /// <returns>
  97. /// <c>true</c> if the object has the specified category; otherwise, <c>false</c>.
  98. /// </returns>
  99. public bool IsInDisabledCategory(Category category)
  100. {
  101. return (DisabledOnCategories & category) == category;
  102. }
  103. /// <summary>
  104. /// Adds the category.
  105. /// </summary>
  106. /// <param name="category">The category.</param>
  107. public void AddEnabledCategory(Category category)
  108. {
  109. EnabledOnCategories |= category;
  110. }
  111. /// <summary>
  112. /// Removes the category.
  113. /// </summary>
  114. /// <param name="category">The category.</param>
  115. public void RemoveEnabledCategory(Category category)
  116. {
  117. EnabledOnCategories &= ~category;
  118. }
  119. /// <summary>
  120. /// Determines whether this body ignores the the specified controller.
  121. /// </summary>
  122. /// <param name="category">The category.</param>
  123. /// <returns>
  124. /// <c>true</c> if the object has the specified category; otherwise, <c>false</c>.
  125. /// </returns>
  126. public bool IsInEnabledCategory(Category category)
  127. {
  128. return (EnabledOnCategories & category) == category;
  129. }
  130. }
  131. [Flags]
  132. public enum WorldFlags
  133. {
  134. /// <summary>
  135. /// Flag that indicates a new fixture has been added to the world.
  136. /// </summary>
  137. NewFixture = (1 << 0),
  138. /// <summary>
  139. /// Flag that clear the forces after each time step.
  140. /// </summary>
  141. ClearForces = (1 << 2),
  142. SubStepping = (1 << 4),
  143. }
  144. /// <summary>
  145. /// The world class manages all physics entities, dynamic simulation,
  146. /// and asynchronous queries.
  147. /// </summary>
  148. public class World
  149. {
  150. /// <summary>
  151. /// Fires whenever a body has been added
  152. /// </summary>
  153. public BodyDelegate BodyAdded;
  154. /// <summary>
  155. /// Fires whenever a body has been removed
  156. /// </summary>
  157. public BodyDelegate BodyRemoved;
  158. internal Queue<Contact> ContactPool = new Queue<Contact>(256);
  159. /// <summary>
  160. /// Fires whenever a fixture has been added
  161. /// </summary>
  162. public FixtureDelegate FixtureAdded;
  163. /// <summary>
  164. /// Fires whenever a fixture has been removed
  165. /// </summary>
  166. public FixtureDelegate FixtureRemoved;
  167. internal WorldFlags Flags;
  168. /// <summary>
  169. /// Fires whenever a joint has been added
  170. /// </summary>
  171. public JointDelegate JointAdded;
  172. /// <summary>
  173. /// Fires whenever a joint has been removed
  174. /// </summary>
  175. public JointDelegate JointRemoved;
  176. public ControllerDelegate ControllerAdded;
  177. public ControllerDelegate ControllerRemoved;
  178. private float _invDt0;
  179. public Island Island = new Island();
  180. private Body[] _stack = new Body[64];
  181. private bool _stepComplete;
  182. private HashSet<Body> _bodyAddList = new HashSet<Body>();
  183. private HashSet<Body> _bodyRemoveList = new HashSet<Body>();
  184. private HashSet<Joint> _jointAddList = new HashSet<Joint>();
  185. private HashSet<Joint> _jointRemoveList = new HashSet<Joint>();
  186. private TOIInput _input = new TOIInput();
  187. /// <summary>
  188. /// If false, the whole simulation stops. It still processes added and removed geometries.
  189. /// </summary>
  190. public bool Enabled = true;
  191. #if (!SILVERLIGHT)
  192. private Stopwatch _watch = new Stopwatch();
  193. #endif
  194. /// <summary>
  195. /// Initializes a new instance of the <see cref="World"/> class.
  196. /// </summary>
  197. private World()
  198. {
  199. Flags = WorldFlags.ClearForces;
  200. ControllerList = new List<Controller>();
  201. BreakableBodyList = new List<BreakableBody>();
  202. BodyList = new List<Body>(32);
  203. JointList = new List<Joint>(32);
  204. }
  205. public World(Vector2 gravity, AABB span)
  206. : this()
  207. {
  208. Gravity = gravity;
  209. ContactManager = new ContactManager(new QuadTreeBroadPhase(span));
  210. }
  211. /// <summary>
  212. /// Initializes a new instance of the <see cref="World"/> class.
  213. /// </summary>
  214. /// <param name="gravity">The gravity.</param>
  215. public World(Vector2 gravity)
  216. : this()
  217. {
  218. ContactManager = new ContactManager(new DynamicTreeBroadPhase());
  219. Gravity = gravity;
  220. }
  221. public List<Controller> ControllerList { get; private set; }
  222. public List<BreakableBody> BreakableBodyList { get; private set; }
  223. public float UpdateTime { get; private set; }
  224. public float ContinuousPhysicsTime { get; private set; }
  225. public float ControllersUpdateTime { get; private set; }
  226. public float AddRemoveTime { get; private set; }
  227. public float ContactsUpdateTime { get; private set; }
  228. public float SolveUpdateTime { get; private set; }
  229. /// <summary>
  230. /// Get the number of broad-phase proxies.
  231. /// </summary>
  232. /// <value>The proxy count.</value>
  233. public int ProxyCount
  234. {
  235. get { return ContactManager.BroadPhase.ProxyCount; }
  236. }
  237. /// <summary>
  238. /// Change the global gravity vector.
  239. /// </summary>
  240. /// <value>The gravity.</value>
  241. public Vector2 Gravity;
  242. /// <summary>
  243. /// Set flag to control automatic clearing of forces after each time step.
  244. /// </summary>
  245. /// <value><c>true</c> if it should auto clear forces; otherwise, <c>false</c>.</value>
  246. public bool AutoClearForces
  247. {
  248. set
  249. {
  250. if (value)
  251. {
  252. Flags |= WorldFlags.ClearForces;
  253. }
  254. else
  255. {
  256. Flags &= ~WorldFlags.ClearForces;
  257. }
  258. }
  259. get { return (Flags & WorldFlags.ClearForces) == WorldFlags.ClearForces; }
  260. }
  261. /// <summary>
  262. /// Get the contact manager for testing.
  263. /// </summary>
  264. /// <value>The contact manager.</value>
  265. public ContactManager ContactManager { get; private set; }
  266. /// <summary>
  267. /// Get the world body list.
  268. /// </summary>
  269. /// <value>Thehead of the world body list.</value>
  270. public List<Body> BodyList { get; private set; }
  271. /// <summary>
  272. /// Get the world joint list.
  273. /// </summary>
  274. /// <value>The joint list.</value>
  275. public List<Joint> JointList { get; private set; }
  276. /// <summary>
  277. /// Get the world contact list. With the returned contact, use Contact.GetNext to get
  278. /// the next contact in the world list. A null contact indicates the end of the list.
  279. /// </summary>
  280. /// <value>The head of the world contact list.</value>
  281. public List<Contact> ContactList
  282. {
  283. get { return ContactManager.ContactList; }
  284. }
  285. /// <summary>
  286. /// Enable/disable single stepped continuous physics. For testing.
  287. /// </summary>
  288. public bool EnableSubStepping
  289. {
  290. set
  291. {
  292. if (value)
  293. {
  294. Flags |= WorldFlags.SubStepping;
  295. }
  296. else
  297. {
  298. Flags &= ~WorldFlags.SubStepping;
  299. }
  300. }
  301. get { return (Flags & WorldFlags.SubStepping) == WorldFlags.SubStepping; }
  302. }
  303. /// <summary>
  304. /// Add a rigid body.
  305. /// </summary>
  306. /// <returns></returns>
  307. internal void AddBody(Body body)
  308. {
  309. Debug.Assert(!_bodyAddList.Contains(body), "You are adding the same body more than once.");
  310. if (!_bodyAddList.Contains(body))
  311. _bodyAddList.Add(body);
  312. }
  313. /// <summary>
  314. /// Destroy a rigid body.
  315. /// Warning: This automatically deletes all associated shapes and joints.
  316. /// </summary>
  317. /// <param name="body">The body.</param>
  318. public void RemoveBody(Body body)
  319. {
  320. Debug.Assert(!_bodyRemoveList.Contains(body),
  321. "The body is already marked for removal. You are removing the body more than once.");
  322. if (!_bodyRemoveList.Contains(body))
  323. _bodyRemoveList.Add(body);
  324. }
  325. /// <summary>
  326. /// Create a joint to constrain bodies together. This may cause the connected bodies to cease colliding.
  327. /// </summary>
  328. /// <param name="joint">The joint.</param>
  329. public void AddJoint(Joint joint)
  330. {
  331. Debug.Assert(!_jointAddList.Contains(joint), "You are adding the same joint more than once.");
  332. if (!_jointAddList.Contains(joint))
  333. _jointAddList.Add(joint);
  334. }
  335. private void RemoveJoint(Joint joint, bool doCheck)
  336. {
  337. if (doCheck)
  338. {
  339. Debug.Assert(!_jointRemoveList.Contains(joint),
  340. "The joint is already marked for removal. You are removing the joint more than once.");
  341. }
  342. if (!_jointRemoveList.Contains(joint))
  343. _jointRemoveList.Add(joint);
  344. }
  345. /// <summary>
  346. /// Destroy a joint. This may cause the connected bodies to begin colliding.
  347. /// </summary>
  348. /// <param name="joint">The joint.</param>
  349. public void RemoveJoint(Joint joint)
  350. {
  351. RemoveJoint(joint, true);
  352. }
  353. /// <summary>
  354. /// All adds and removes are cached by the World duing a World step.
  355. /// To process the changes before the world updates again, call this method.
  356. /// </summary>
  357. public void ProcessChanges()
  358. {
  359. ProcessAddedBodies();
  360. ProcessAddedJoints();
  361. ProcessRemovedBodies();
  362. ProcessRemovedJoints();
  363. }
  364. private void ProcessRemovedJoints()
  365. {
  366. if (_jointRemoveList.Count > 0)
  367. {
  368. foreach (Joint joint in _jointRemoveList)
  369. {
  370. bool collideConnected = joint.CollideConnected;
  371. // Remove from the world list.
  372. JointList.Remove(joint);
  373. // Disconnect from island graph.
  374. Body bodyA = joint.BodyA;
  375. Body bodyB = joint.BodyB;
  376. // Wake up connected bodies.
  377. bodyA.Awake = true;
  378. // WIP David
  379. if (!joint.IsFixedType())
  380. {
  381. bodyB.Awake = true;
  382. }
  383. // Remove from body 1.
  384. if (joint.EdgeA.Prev != null)
  385. {
  386. joint.EdgeA.Prev.Next = joint.EdgeA.Next;
  387. }
  388. if (joint.EdgeA.Next != null)
  389. {
  390. joint.EdgeA.Next.Prev = joint.EdgeA.Prev;
  391. }
  392. if (joint.EdgeA == bodyA.JointList)
  393. {
  394. bodyA.JointList = joint.EdgeA.Next;
  395. }
  396. joint.EdgeA.Prev = null;
  397. joint.EdgeA.Next = null;
  398. // WIP David
  399. if (!joint.IsFixedType())
  400. {
  401. // Remove from body 2
  402. if (joint.EdgeB.Prev != null)
  403. {
  404. joint.EdgeB.Prev.Next = joint.EdgeB.Next;
  405. }
  406. if (joint.EdgeB.Next != null)
  407. {
  408. joint.EdgeB.Next.Prev = joint.EdgeB.Prev;
  409. }
  410. if (joint.EdgeB == bodyB.JointList)
  411. {
  412. bodyB.JointList = joint.EdgeB.Next;
  413. }
  414. joint.EdgeB.Prev = null;
  415. joint.EdgeB.Next = null;
  416. }
  417. // WIP David
  418. if (!joint.IsFixedType())
  419. {
  420. // If the joint prevents collisions, then flag any contacts for filtering.
  421. if (collideConnected == false)
  422. {
  423. ContactEdge edge = bodyB.ContactList;
  424. while (edge != null)
  425. {
  426. if (edge.Other == bodyA)
  427. {
  428. // Flag the contact for filtering at the next time step (where either
  429. // body is awake).
  430. edge.Contact.FlagForFiltering();
  431. }
  432. edge = edge.Next;
  433. }
  434. }
  435. }
  436. if (JointRemoved != null)
  437. {
  438. JointRemoved(joint);
  439. }
  440. }
  441. _jointRemoveList.Clear();
  442. }
  443. }
  444. private void ProcessAddedJoints()
  445. {
  446. if (_jointAddList.Count > 0)
  447. {
  448. foreach (Joint joint in _jointAddList)
  449. {
  450. // Connect to the world list.
  451. JointList.Add(joint);
  452. // Connect to the bodies' doubly linked lists.
  453. joint.EdgeA.Joint = joint;
  454. joint.EdgeA.Other = joint.BodyB;
  455. joint.EdgeA.Prev = null;
  456. joint.EdgeA.Next = joint.BodyA.JointList;
  457. if (joint.BodyA.JointList != null)
  458. joint.BodyA.JointList.Prev = joint.EdgeA;
  459. joint.BodyA.JointList = joint.EdgeA;
  460. // WIP David
  461. if (!joint.IsFixedType())
  462. {
  463. joint.EdgeB.Joint = joint;
  464. joint.EdgeB.Other = joint.BodyA;
  465. joint.EdgeB.Prev = null;
  466. joint.EdgeB.Next = joint.BodyB.JointList;
  467. if (joint.BodyB.JointList != null)
  468. joint.BodyB.JointList.Prev = joint.EdgeB;
  469. joint.BodyB.JointList = joint.EdgeB;
  470. Body bodyA = joint.BodyA;
  471. Body bodyB = joint.BodyB;
  472. // If the joint prevents collisions, then flag any contacts for filtering.
  473. if (joint.CollideConnected == false)
  474. {
  475. ContactEdge edge = bodyB.ContactList;
  476. while (edge != null)
  477. {
  478. if (edge.Other == bodyA)
  479. {
  480. // Flag the contact for filtering at the next time step (where either
  481. // body is awake).
  482. edge.Contact.FlagForFiltering();
  483. }
  484. edge = edge.Next;
  485. }
  486. }
  487. }
  488. if (JointAdded != null)
  489. JointAdded(joint);
  490. // Note: creating a joint doesn't wake the bodies.
  491. }
  492. _jointAddList.Clear();
  493. }
  494. }
  495. private void ProcessAddedBodies()
  496. {
  497. if (_bodyAddList.Count > 0)
  498. {
  499. foreach (Body body in _bodyAddList)
  500. {
  501. // Add to world list.
  502. BodyList.Add(body);
  503. if (BodyAdded != null)
  504. BodyAdded(body);
  505. }
  506. _bodyAddList.Clear();
  507. }
  508. }
  509. private void ProcessRemovedBodies()
  510. {
  511. if (_bodyRemoveList.Count > 0)
  512. {
  513. foreach (Body body in _bodyRemoveList)
  514. {
  515. Debug.Assert(BodyList.Count > 0);
  516. // You tried to remove a body that is not contained in the BodyList.
  517. // Are you removing the body more than once?
  518. Debug.Assert(BodyList.Contains(body));
  519. // Delete the attached joints.
  520. JointEdge je = body.JointList;
  521. while (je != null)
  522. {
  523. JointEdge je0 = je;
  524. je = je.Next;
  525. RemoveJoint(je0.Joint, false);
  526. }
  527. body.JointList = null;
  528. // Delete the attached contacts.
  529. ContactEdge ce = body.ContactList;
  530. while (ce != null)
  531. {
  532. ContactEdge ce0 = ce;
  533. ce = ce.Next;
  534. ContactManager.Destroy(ce0.Contact);
  535. }
  536. body.ContactList = null;
  537. // Delete the attached fixtures. This destroys broad-phase proxies.
  538. for (int i = 0; i < body.FixtureList.Count; i++)
  539. {
  540. body.FixtureList[i].DestroyProxies(ContactManager.BroadPhase);
  541. body.FixtureList[i].Destroy();
  542. }
  543. body.FixtureList = null;
  544. // Remove world body list.
  545. BodyList.Remove(body);
  546. if (BodyRemoved != null)
  547. BodyRemoved(body);
  548. }
  549. _bodyRemoveList.Clear();
  550. }
  551. }
  552. /// <summary>
  553. /// Take a time step. This performs collision detection, integration,
  554. /// and consraint solution.
  555. /// </summary>
  556. /// <param name="dt">The amount of time to simulate, this should not vary.</param>
  557. public void Step(float dt)
  558. {
  559. #if (!SILVERLIGHT)
  560. if (Settings.EnableDiagnostics)
  561. _watch.Start();
  562. #endif
  563. ProcessChanges();
  564. #if (!SILVERLIGHT)
  565. if (Settings.EnableDiagnostics)
  566. AddRemoveTime = _watch.ElapsedTicks;
  567. #endif
  568. //If there is no change in time, no need to calculate anything.
  569. if (dt == 0 || !Enabled)
  570. {
  571. #if (!SILVERLIGHT)
  572. if (Settings.EnableDiagnostics)
  573. {
  574. _watch.Stop();
  575. _watch.Reset();
  576. }
  577. #endif
  578. return;
  579. }
  580. // If new fixtures were added, we need to find the new contacts.
  581. if ((Flags & WorldFlags.NewFixture) == WorldFlags.NewFixture)
  582. {
  583. ContactManager.FindNewContacts();
  584. Flags &= ~WorldFlags.NewFixture;
  585. }
  586. TimeStep step;
  587. step.inv_dt = 1.0f / dt;
  588. step.dt = dt;
  589. step.dtRatio = _invDt0 * dt;
  590. //Update controllers
  591. for (int i = 0; i < ControllerList.Count; i++)
  592. {
  593. ControllerList[i].Update(dt);
  594. }
  595. #if (!SILVERLIGHT)
  596. if (Settings.EnableDiagnostics)
  597. ControllersUpdateTime = _watch.ElapsedTicks - AddRemoveTime;
  598. #endif
  599. // Update contacts. This is where some contacts are destroyed.
  600. ContactManager.Collide();
  601. #if (!SILVERLIGHT)
  602. if (Settings.EnableDiagnostics)
  603. ContactsUpdateTime = _watch.ElapsedTicks - (AddRemoveTime + ControllersUpdateTime);
  604. #endif
  605. // Integrate velocities, solve velocity raints, and integrate positions.
  606. Solve(ref step);
  607. #if (!SILVERLIGHT)
  608. if (Settings.EnableDiagnostics)
  609. SolveUpdateTime = _watch.ElapsedTicks - (AddRemoveTime + ControllersUpdateTime + ContactsUpdateTime);
  610. #endif
  611. // Handle TOI events.
  612. if (Settings.ContinuousPhysics)
  613. {
  614. SolveTOI(ref step);
  615. }
  616. #if (!SILVERLIGHT)
  617. if (Settings.EnableDiagnostics)
  618. ContinuousPhysicsTime = _watch.ElapsedTicks -
  619. (AddRemoveTime + ControllersUpdateTime + ContactsUpdateTime + SolveUpdateTime);
  620. #endif
  621. _invDt0 = step.inv_dt;
  622. if ((Flags & WorldFlags.ClearForces) != 0)
  623. {
  624. ClearForces();
  625. }
  626. for (int i = 0; i < BreakableBodyList.Count; i++)
  627. {
  628. BreakableBodyList[i].Update();
  629. }
  630. #if (!SILVERLIGHT)
  631. if (Settings.EnableDiagnostics)
  632. {
  633. _watch.Stop();
  634. //AddRemoveTime = 1000 * AddRemoveTime / Stopwatch.Frequency;
  635. UpdateTime = _watch.ElapsedTicks;
  636. _watch.Reset();
  637. }
  638. #endif
  639. }
  640. /// <summary>
  641. /// Call this after you are done with time steps to clear the forces. You normally
  642. /// call this after each call to Step, unless you are performing sub-steps. By default,
  643. /// forces will be automatically cleared, so you don't need to call this function.
  644. /// </summary>
  645. public void ClearForces()
  646. {
  647. for (int i = 0; i < BodyList.Count; i++)
  648. {
  649. Body body = BodyList[i];
  650. body.Force = Vector2.Zero;
  651. body.Torque = 0.0f;
  652. }
  653. }
  654. /// <summary>
  655. /// Query the world for all fixtures that potentially overlap the
  656. /// provided AABB.
  657. ///
  658. /// Inside the callback:
  659. /// Return true: Continues the query
  660. /// Return false: Terminate the query
  661. /// </summary>
  662. /// <param name="callback">A user implemented callback class.</param>
  663. /// <param name="aabb">The aabb query box.</param>
  664. public void QueryAABB(Func<Fixture, bool> callback, ref AABB aabb)
  665. {
  666. ContactManager.BroadPhase.Query(proxyId =>
  667. {
  668. FixtureProxy proxy = ContactManager.BroadPhase.GetProxy(proxyId);
  669. return callback(proxy.Fixture);
  670. }, ref aabb);
  671. }
  672. /// <summary>
  673. /// Ray-cast the world for all fixtures in the path of the ray. Your callback
  674. /// controls whether you get the closest point, any point, or n-points.
  675. /// The ray-cast ignores shapes that contain the starting point.
  676. ///
  677. /// Inside the callback:
  678. /// return -1: ignore this fixture and continue
  679. /// return 0: terminate the ray cast
  680. /// return fraction: clip the ray to this point
  681. /// return 1: don't clip the ray and continue
  682. /// </summary>
  683. /// <param name="callback">A user implemented callback class.</param>
  684. /// <param name="point1">The ray starting point.</param>
  685. /// <param name="point2">The ray ending point.</param>
  686. public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
  687. {
  688. RayCastInput input = new RayCastInput();
  689. input.MaxFraction = 1.0f;
  690. input.Point1 = point1;
  691. input.Point2 = point2;
  692. ContactManager.BroadPhase.RayCast((rayCastInput, proxyId) =>
  693. {
  694. FixtureProxy proxy = ContactManager.BroadPhase.GetProxy(proxyId);
  695. Fixture fixture = proxy.Fixture;
  696. int index = proxy.ChildIndex;
  697. RayCastOutput output;
  698. bool hit = fixture.RayCast(out output, ref rayCastInput, index);
  699. if (hit)
  700. {
  701. float fraction = output.Fraction;
  702. Vector2 point = (1.0f - fraction) * input.Point1 +
  703. fraction * input.Point2;
  704. return callback(fixture, point, output.Normal, fraction);
  705. }
  706. return input.MaxFraction;
  707. }, ref input);
  708. }
  709. private void Solve(ref TimeStep step)
  710. {
  711. // Size the island for the worst case.
  712. Island.Reset(BodyList.Count,
  713. ContactManager.ContactList.Count,
  714. JointList.Count,
  715. ContactManager);
  716. // Clear all the island flags.
  717. foreach (Body b in BodyList)
  718. {
  719. b.Flags &= ~BodyFlags.Island;
  720. }
  721. for (int i = 0; i < ContactManager.ContactList.Count; i++)
  722. {
  723. Contact c = ContactManager.ContactList[i];
  724. c.Flags &= ~ContactFlags.Island;
  725. }
  726. foreach (Joint j in JointList)
  727. {
  728. j.IslandFlag = false;
  729. }
  730. // Build and simulate all awake islands.
  731. int stackSize = BodyList.Count;
  732. if (stackSize > _stack.Length)
  733. _stack = new Body[Math.Max(_stack.Length * 2, stackSize)];
  734. for (int index = BodyList.Count - 1; index >= 0; index--)
  735. {
  736. Body seed = BodyList[index];
  737. if ((seed.Flags & (BodyFlags.Island)) != BodyFlags.None)
  738. {
  739. continue;
  740. }
  741. if (seed.Awake == false || seed.Enabled == false)
  742. {
  743. continue;
  744. }
  745. // The seed can be dynamic or kinematic.
  746. if (seed.BodyType == BodyType.Static)
  747. {
  748. continue;
  749. }
  750. // Reset island and stack.
  751. Island.Clear();
  752. int stackCount = 0;
  753. _stack[stackCount++] = seed;
  754. seed.Flags |= BodyFlags.Island;
  755. // Perform a depth first search (DFS) on the constraint graph.
  756. while (stackCount > 0)
  757. {
  758. // Grab the next body off the stack and add it to the island.
  759. Body b = _stack[--stackCount];
  760. Debug.Assert(b.Enabled);
  761. Island.Add(b);
  762. // Make sure the body is awake.
  763. b.Awake = true;
  764. // To keep islands as small as possible, we don't
  765. // propagate islands across static bodies.
  766. if (b.BodyType == BodyType.Static)
  767. {
  768. continue;
  769. }
  770. // Search all contacts connected to this body.
  771. for (ContactEdge ce = b.ContactList; ce != null; ce = ce.Next)
  772. {
  773. Contact contact = ce.Contact;
  774. // Has this contact already been added to an island?
  775. if ((contact.Flags & ContactFlags.Island) != ContactFlags.None)
  776. {
  777. continue;
  778. }
  779. // Is this contact solid and touching?
  780. if (!ce.Contact.Enabled || !ce.Contact.IsTouching())
  781. {
  782. continue;
  783. }
  784. // Skip sensors.
  785. bool sensorA = contact.FixtureA.IsSensor;
  786. bool sensorB = contact.FixtureB.IsSensor;
  787. if (sensorA || sensorB)
  788. {
  789. continue;
  790. }
  791. Island.Add(contact);
  792. contact.Flags |= ContactFlags.Island;
  793. Body other = ce.Other;
  794. // Was the other body already added to this island?
  795. if ((other.Flags & BodyFlags.Island) != BodyFlags.None)
  796. {
  797. continue;
  798. }
  799. Debug.Assert(stackCount < stackSize);
  800. _stack[stackCount++] = other;
  801. other.Flags |= BodyFlags.Island;
  802. }
  803. // Search all joints connect to this body.
  804. for (JointEdge je = b.JointList; je != null; je = je.Next)
  805. {
  806. if (je.Joint.IslandFlag)
  807. {
  808. continue;
  809. }
  810. Body other = je.Other;
  811. // WIP David
  812. //Enter here when it's a non-fixed joint. Non-fixed joints have a other body.
  813. if (other != null)
  814. {
  815. // Don't simulate joints connected to inactive bodies.
  816. if (other.Enabled == false)
  817. {
  818. continue;
  819. }
  820. Island.Add(je.Joint);
  821. je.Joint.IslandFlag = true;
  822. if ((other.Flags & BodyFlags.Island) != BodyFlags.None)
  823. {
  824. continue;
  825. }
  826. Debug.Assert(stackCount < stackSize);
  827. _stack[stackCount++] = other;
  828. other.Flags |= BodyFlags.Island;
  829. }
  830. else
  831. {
  832. Island.Add(je.Joint);
  833. je.Joint.IslandFlag = true;
  834. }
  835. }
  836. }
  837. Island.Solve(ref step, ref Gravity);
  838. // Post solve cleanup.
  839. for (int i = 0; i < Island.BodyCount; ++i)
  840. {
  841. // Allow static bodies to participate in other islands.
  842. Body b = Island.Bodies[i];
  843. if (b.BodyType == BodyType.Static)
  844. {
  845. b.Flags &= ~BodyFlags.Island;
  846. }
  847. }
  848. }
  849. // Synchronize fixtures, check for out of range bodies.
  850. foreach (Body b in BodyList)
  851. {
  852. // If a body was not in an island then it did not move.
  853. if ((b.Flags & BodyFlags.Island) != BodyFlags.Island)
  854. {
  855. continue;
  856. }
  857. if (b.BodyType == BodyType.Static)
  858. {
  859. continue;
  860. }
  861. // Update fixtures (for broad-phase).
  862. b.SynchronizeFixtures();
  863. }
  864. // Look for new contacts.
  865. ContactManager.FindNewContacts();
  866. }
  867. /// <summary>
  868. /// Find TOI contacts and solve them.
  869. /// </summary>
  870. /// <param name="step">The step.</param>
  871. private void SolveTOI(ref TimeStep step)
  872. {
  873. Island.Reset(2 * Settings.MaxTOIContacts, Settings.MaxTOIContacts, 0, ContactManager);
  874. if (_stepComplete)
  875. {
  876. for (int i = 0; i < BodyList.Count; i++)
  877. {
  878. BodyList[i].Flags &= ~BodyFlags.Island;
  879. BodyList[i].Sweep.Alpha0 = 0.0f;
  880. }
  881. for (int i = 0; i < ContactManager.ContactList.Count; i++)
  882. {
  883. Contact c = ContactManager.ContactList[i];
  884. // Invalidate TOI
  885. c.Flags &= ~(ContactFlags.TOI | ContactFlags.Island);
  886. c.TOICount = 0;
  887. c.TOI = 1.0f;
  888. }
  889. }
  890. // Find TOI events and solve them.
  891. for (; ; )
  892. {
  893. // Find the first TOI.
  894. Contact minContact = null;
  895. float minAlpha = 1.0f;
  896. for (int i = 0; i < ContactManager.ContactList.Count; i++)
  897. {
  898. Contact c = ContactManager.ContactList[i];
  899. // Is this contact disabled?
  900. if (c.Enabled == false)
  901. {
  902. continue;
  903. }
  904. // Prevent excessive sub-stepping.
  905. if (c.TOICount > Settings.MaxSubSteps)
  906. {
  907. continue;
  908. }
  909. float alpha;
  910. if ((c.Flags & ContactFlags.TOI) == ContactFlags.TOI)
  911. {
  912. // This contact has a valid cached TOI.
  913. alpha = c.TOI;
  914. }
  915. else
  916. {
  917. Fixture fA = c.FixtureA;
  918. Fixture fB = c.FixtureB;
  919. // Is there a sensor?
  920. if (fA.IsSensor || fB.IsSensor)
  921. {
  922. continue;
  923. }
  924. Body bA = fA.Body;
  925. Body bB = fB.Body;
  926. BodyType typeA = bA.BodyType;
  927. BodyType typeB = bB.BodyType;
  928. Debug.Assert(typeA == BodyType.Dynamic || typeB == BodyType.Dynamic);
  929. bool awakeA = bA.Awake && typeA != BodyType.Static;
  930. bool awakeB = bB.Awake && typeB != BodyType.Static;
  931. // Is at least one body awake?
  932. if (awakeA == false && awakeB == false)
  933. {
  934. continue;
  935. }
  936. bool collideA = (bA.IsBullet || typeA != BodyType.Dynamic) && !bA.IgnoreCCD;
  937. bool collideB = (bB.IsBullet || typeB != BodyType.Dynamic) && !bB.IgnoreCCD;
  938. // Are these two non-bullet dynamic bodies?
  939. if (collideA == false && collideB == false)
  940. {
  941. continue;
  942. }
  943. // Compute the TOI for this contact.
  944. // Put the sweeps onto the same time interval.
  945. float alpha0 = bA.Sweep.Alpha0;
  946. if (bA.Sweep.Alpha0 < bB.Sweep.Alpha0)
  947. {
  948. alpha0 = bB.Sweep.Alpha0;
  949. bA.Sweep.Advance(alpha0);
  950. }
  951. else if (bB.Sweep.Alpha0 < bA.Sweep.Alpha0)
  952. {
  953. alpha0 = bA.Sweep.Alpha0;
  954. bB.Sweep.Advance(alpha0);
  955. }
  956. Debug.Assert(alpha0 < 1.0f);
  957. // Compute the time of impact in interval [0, minTOI]
  958. _input.ProxyA.Set(fA.Shape, c.ChildIndexA);
  959. _input.ProxyB.Set(fB.Shape, c.ChildIndexB);
  960. _input.SweepA = bA.Sweep;
  961. _input.SweepB = bB.Sweep;
  962. _input.TMax = 1.0f;
  963. TOIOutput output;
  964. TimeOfImpact.CalculateTimeOfImpact(out output, _input);
  965. // Beta is the fraction of the remaining portion of the .
  966. float beta = output.T;
  967. if (output.State == TOIOutputState.Touching)
  968. {
  969. alpha = Math.Min(alpha0 + (1.0f - alpha0) * beta, 1.0f);
  970. }
  971. else
  972. {
  973. alpha = 1.0f;
  974. }
  975. c.TOI = alpha;
  976. c.Flags |= ContactFlags.TOI;
  977. }
  978. if (alpha < minAlpha)
  979. {
  980. // This is the minimum TOI found so far.
  981. minContact = c;
  982. minAlpha = alpha;
  983. }
  984. }
  985. if (minContact == null || 1.0f - 10.0f * Settings.Epsilon < minAlpha)
  986. {
  987. // No more TOI events. Done!
  988. _stepComplete = true;
  989. break;
  990. }
  991. // Advance the bodies to the TOI.
  992. Fixture fA1 = minContact.FixtureA;
  993. Fixture fB1 = minContact.FixtureB;
  994. Body bA1 = fA1.Body;
  995. Body bB1 = fB1.Body;
  996. Sweep backup1 = bA1.Sweep;
  997. Sweep backup2 = bB1.Sweep;
  998. bA1.Advance(minAlpha);
  999. bB1.Advance(minAlpha);
  1000. // The TOI contact likely has some new contact points.
  1001. minContact.Update(ContactManager);
  1002. minContact.Flags &= ~ContactFlags.TOI;
  1003. ++minContact.TOICount;
  1004. // Is the contact solid?
  1005. if (minContact.Enabled == false || minContact.IsTouching() == false)
  1006. {
  1007. // Restore the sweeps.
  1008. minContact.Enabled = false;
  1009. bA1.Sweep = backup1;
  1010. bB1.Sweep = backup2;
  1011. bA1.SynchronizeTransform();
  1012. bB1.SynchronizeTransform();
  1013. continue;
  1014. }
  1015. bA1.Awake = true;
  1016. bB1.Awake = true;
  1017. // Build the island
  1018. Island.Clear();
  1019. Island.Add(bA1);
  1020. Island.Add(bB1);
  1021. Island.Add(minContact);
  1022. bA1.Flags |= BodyFlags.Island;
  1023. bB1.Flags |= BodyFlags.Island;
  1024. minContact.Flags |= ContactFlags.Island;
  1025. // Get contacts on bodyA and bodyB.
  1026. Body[] bodies = { bA1, bB1 };
  1027. for (int i = 0; i < 2; ++i)
  1028. {
  1029. Body body = bodies[i];
  1030. if (body.BodyType == BodyType.Dynamic)
  1031. {
  1032. // for (ContactEdge ce = body.ContactList; ce && Island.BodyCount < Settings.MaxTOIContacts; ce = ce.Next)
  1033. for (ContactEdge ce = body.ContactList; ce != null; ce = ce.Next)
  1034. {
  1035. Contact contact = ce.Contact;
  1036. // Has this contact already been added to the island?
  1037. if ((contact.Flags & ContactFlags.Island) == ContactFlags.Island)
  1038. {
  1039. continue;
  1040. }
  1041. // Only add static, kinematic, or bullet bodies.
  1042. Body other = ce.Other;
  1043. if (other.BodyType == BodyType.Dynamic &&
  1044. body.IsBullet == false && other.IsBullet == false)
  1045. {
  1046. continue;
  1047. }
  1048. // Skip sensors.
  1049. if (contact.FixtureA.IsSensor || contact.FixtureB.IsSensor)
  1050. {
  1051. continue;
  1052. }
  1053. // Tentatively advance the body to the TOI.
  1054. Sweep backup = other.Sweep;
  1055. if ((other.Flags & BodyFlags.Island) == 0)
  1056. {
  1057. other.Advance(minAlpha);
  1058. }
  1059. // Update the contact points
  1060. contact.Update(ContactManager);
  1061. // Was the contact disabled by the user?
  1062. if (contact.Enabled == false)
  1063. {
  1064. other.Sweep = backup;
  1065. other.SynchronizeTransform();
  1066. continue;
  1067. }
  1068. // Are there contact points?
  1069. if (contact.IsTouching() == false)
  1070. {
  1071. other.Sweep = backup;
  1072. other.SynchronizeTransform();
  1073. continue;
  1074. }
  1075. // Add the contact to the island
  1076. contact.Flags |= ContactFlags.Island;
  1077. Island.Add(contact);
  1078. // Has the other body already been added to the island?
  1079. if ((other.Flags & BodyFlags.Island) == BodyFlags.Island)
  1080. {
  1081. continue;
  1082. }
  1083. // Add the other body to the island.
  1084. other.Flags |= BodyFlags.Island;
  1085. if (other.BodyType != BodyType.Static)
  1086. {
  1087. other.Awake = true;
  1088. }
  1089. Island.Add(other);
  1090. }
  1091. }
  1092. }
  1093. TimeStep subStep;
  1094. subStep.dt = (1.0f - minAlpha) * step.dt;
  1095. subStep.inv_dt = 1.0f / subStep.dt;
  1096. subStep.dtRatio = 1.0f;
  1097. //subStep.positionIterations = 20;
  1098. //subStep.velocityIterations = step.velocityIterations;
  1099. //subStep.warmStarting = false;
  1100. Island.SolveTOI(ref subStep);
  1101. // Reset island flags and synchronize broad-phase proxies.
  1102. for (int i = 0; i < Island.BodyCount; ++i)
  1103. {
  1104. Body body = Island.Bodies[i];
  1105. body.Flags &= ~BodyFlags.Island;
  1106. if (body.BodyType != BodyType.Dynamic)
  1107. {
  1108. continue;
  1109. }
  1110. body.SynchronizeFixtures();
  1111. // Invalidate all contact TOIs on this displaced body.
  1112. for (ContactEdge ce = body.ContactList; ce != null; ce = ce.Next)
  1113. {
  1114. ce.Contact.Flags &= ~(ContactFlags.TOI | ContactFlags.Island);
  1115. }
  1116. }
  1117. // Commit fixture proxy movements to the broad-phase so that new contacts are created.
  1118. // Also, some contacts can be destroyed.
  1119. ContactManager.FindNewContacts();
  1120. if (EnableSubStepping)
  1121. {
  1122. _stepComplete = false;
  1123. break;
  1124. }
  1125. }
  1126. }
  1127. public void AddController(Controller controller)
  1128. {
  1129. Debug.Assert(!ControllerList.Contains(controller), "You are adding the same controller more than once.");
  1130. controller.World = this;
  1131. ControllerList.Add(controller);
  1132. if (ControllerAdded != null)
  1133. ControllerAdded(controller);
  1134. }
  1135. public void RemoveController(Controller controller)
  1136. {
  1137. Debug.Assert(ControllerList.Contains(controller),
  1138. "You are removing a controller that is not in the simulation.");
  1139. if (ControllerList.Contains(controller))
  1140. {
  1141. ControllerList.Remove(controller);
  1142. if (ControllerRemoved != null)
  1143. ControllerRemoved(controller);
  1144. }
  1145. }
  1146. public void AddBreakableBody(BreakableBody breakableBody)
  1147. {
  1148. BreakableBodyList.Add(breakableBody);
  1149. }
  1150. public void RemoveBreakableBody(BreakableBody breakableBody)
  1151. {
  1152. //The breakable body list does not contain the body you tried to remove.
  1153. Debug.Assert(BreakableBodyList.Contains(breakableBody));
  1154. BreakableBodyList.Remove(breakableBody);
  1155. }
  1156. public Fixture TestPoint(Vector2 point)
  1157. {
  1158. AABB aabb;
  1159. Vector2 d = new Vector2(Settings.Epsilon, Settings.Epsilon);
  1160. aabb.LowerBound = point - d;
  1161. aabb.UpperBound = point + d;
  1162. Fixture myFixture = null;
  1163. // Query the world for overlapping shapes.
  1164. QueryAABB(
  1165. fixture =>
  1166. {
  1167. bool inside = fixture.TestPoint(ref point);
  1168. if (inside)
  1169. {
  1170. myFixture = fixture;
  1171. return false;
  1172. }
  1173. // Continue the query.
  1174. return true;
  1175. }, ref aabb);
  1176. return myFixture;
  1177. }
  1178. /// <summary>
  1179. /// Returns a list of fixtures that are at the specified point.
  1180. /// </summary>
  1181. /// <param name="point">The point.</param>
  1182. /// <returns></returns>
  1183. public List<Fixture> TestPointAll(Vector2 point)
  1184. {
  1185. AABB aabb;
  1186. Vector2 d = new Vector2(Settings.Epsilon, Settings.Epsilon);
  1187. aabb.LowerBound = point - d;
  1188. aabb.UpperBound = point + d;
  1189. List<Fixture> fixtures = new List<Fixture>();
  1190. // Query the world for overlapping shapes.
  1191. QueryAABB(
  1192. fixture =>
  1193. {
  1194. bool inside = fixture.TestPoint(ref point);
  1195. if (inside)
  1196. fixtures.Add(fixture);
  1197. // Continue the query.
  1198. return true;
  1199. }, ref aabb);
  1200. return fixtures;
  1201. }
  1202. public void Clear()
  1203. {
  1204. ProcessChanges();
  1205. for (int i = BodyList.Count - 1; i >= 0; i--)
  1206. {
  1207. RemoveBody(BodyList[i]);
  1208. }
  1209. for (int i = ControllerList.Count - 1; i >= 0; i--)
  1210. {
  1211. RemoveController(ControllerList[i]);
  1212. }
  1213. for (int i = BreakableBodyList.Count - 1; i >= 0; i--)
  1214. {
  1215. RemoveBreakableBody(BreakableBodyList[i]);
  1216. }
  1217. ProcessChanges();
  1218. }
  1219. }
  1220. }