World.cs 39 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292
  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. using Microsoft.Xna.Framework.Graphics;
  26. using System.Collections.Generic;
  27. namespace Box2D.XNA
  28. {
  29. [Flags]
  30. public enum WorldFlags
  31. {
  32. NewFixture = (1 << 0),
  33. Locked = (1 << 1),
  34. ClearForces = (1 << 2),
  35. };
  36. /// The world class manages all physics entities, dynamic simulation,
  37. /// and asynchronous queries. The world also contains efficient memory
  38. /// management facilities.
  39. public class World
  40. {
  41. /// ruct a world object.
  42. /// @param gravity the world gravity vector.
  43. /// @param doSleep improve performance by not simulating inactive bodies.
  44. public World(Vector2 gravity, bool doSleep)
  45. {
  46. WarmStarting = true;
  47. ContinuousPhysics = true;
  48. _allowSleep = doSleep;
  49. Gravity = gravity;
  50. _flags = WorldFlags.ClearForces;
  51. _queryAABBCallbackWrapper = QueryAABBCallbackWrapper;
  52. _rayCastCallbackWrapper = RayCastCallbackWrapper;
  53. }
  54. /// Register a destruction listener.
  55. public IDestructionListener DestructionListener { get; set; }
  56. /// Register a contact filter to provide specific control over collision.
  57. /// Otherwise the default filter is used (Settings.b2_defaultFilter).
  58. public IContactFilter ContactFilter
  59. {
  60. get
  61. {
  62. return _contactManager.ContactFilter;
  63. }
  64. set
  65. {
  66. _contactManager.ContactFilter = value;
  67. }
  68. }
  69. /// Register a contact event listener
  70. public IContactListener ContactListener
  71. {
  72. get
  73. {
  74. return _contactManager.ContactListener;
  75. }
  76. set
  77. {
  78. _contactManager.ContactListener = value;
  79. }
  80. }
  81. /// Register a routine for debug drawing. The debug draw functions are called
  82. /// inside the World.Step method, so make sure your renderer is ready to
  83. /// consume draw commands when you call Step().
  84. public DebugDraw DebugDraw { get; set; }
  85. /// Create a rigid body given a definition. No reference to the definition
  86. /// is retained.
  87. /// @warning This function is locked during callbacks.
  88. public Body CreateBody(BodyDef def)
  89. {
  90. Debug.Assert(!IsLocked);
  91. if (IsLocked)
  92. {
  93. return null;
  94. }
  95. var b = new Body(def, this);
  96. // Add to world doubly linked list.
  97. b._prev = null;
  98. b._next = _bodyList;
  99. if (_bodyList != null)
  100. {
  101. _bodyList._prev = b;
  102. }
  103. _bodyList = b;
  104. ++_bodyCount;
  105. return b;
  106. }
  107. /// Destroy a rigid body given a definition. No reference to the definition
  108. /// is retained. This function is locked during callbacks.
  109. /// @warning This automatically deletes all associated shapes and joints.
  110. /// @warning This function is locked during callbacks.
  111. public void DestroyBody(Body b)
  112. {
  113. Debug.Assert(_bodyCount > 0);
  114. Debug.Assert(!IsLocked);
  115. if (IsLocked)
  116. {
  117. return;
  118. }
  119. // Delete the attached joints.
  120. JointEdge je = b._jointList;
  121. while (je != null)
  122. {
  123. JointEdge je0 = je;
  124. je = je.Next;
  125. if (DestructionListener != null)
  126. {
  127. DestructionListener.SayGoodbye(je0.Joint);
  128. }
  129. DestroyJoint(je0.Joint);
  130. }
  131. b._jointList = null;
  132. // Delete the attached contacts.
  133. ContactEdge ce = b._contactList;
  134. while (ce != null)
  135. {
  136. ContactEdge ce0 = ce;
  137. ce = ce.Next;
  138. _contactManager.Destroy(ce0.Contact);
  139. }
  140. b._contactList = null;
  141. // Delete the attached fixtures. This destroys broad-phase proxies.
  142. Fixture f = b._fixtureList;
  143. while (f != null)
  144. {
  145. Fixture f0 = f;
  146. f = f._next;
  147. if (DestructionListener != null)
  148. {
  149. DestructionListener.SayGoodbye(f0);
  150. }
  151. f0.DestroyProxies(_contactManager._broadPhase);
  152. f0.Destroy();
  153. }
  154. b._fixtureList = null;
  155. b._fixtureCount = 0;
  156. // Remove world body list.
  157. if (b._prev != null)
  158. {
  159. b._prev._next = b._next;
  160. }
  161. if (b._next != null)
  162. {
  163. b._next._prev = b._prev;
  164. }
  165. if (b == _bodyList)
  166. {
  167. _bodyList = b._next;
  168. }
  169. --_bodyCount;
  170. }
  171. /// Create a joint to rain bodies together. No reference to the definition
  172. /// is retained. This may cause the connected bodies to cease colliding.
  173. /// @warning This function is locked during callbacks.
  174. public Joint CreateJoint(JointDef def)
  175. {
  176. Debug.Assert(!IsLocked);
  177. if (IsLocked)
  178. {
  179. return null;
  180. }
  181. Joint j = Joint.Create(def);
  182. // Connect to the world list.
  183. j._prev = null;
  184. j._next = _jointList;
  185. if (_jointList != null)
  186. {
  187. _jointList._prev = j;
  188. }
  189. _jointList = j;
  190. ++_jointCount;
  191. // Connect to the bodies' doubly linked lists.
  192. j._edgeA.Joint = j;
  193. j._edgeA.Other = j._bodyB;
  194. j._edgeA.Prev = null;
  195. j._edgeA.Next = j._bodyA._jointList;
  196. if (j._bodyA._jointList != null)
  197. j._bodyA._jointList.Prev = j._edgeA;
  198. j._bodyA._jointList = j._edgeA;
  199. j._edgeB.Joint = j;
  200. j._edgeB.Other = j._bodyA;
  201. j._edgeB.Prev = null;
  202. j._edgeB.Next = j._bodyB._jointList;
  203. if (j._bodyB._jointList != null)
  204. j._bodyB._jointList.Prev = j._edgeB;
  205. j._bodyB._jointList = j._edgeB;
  206. Body bodyA = def.bodyA;
  207. Body bodyB = def.bodyB;
  208. bool staticA = bodyA.GetType() == BodyType.Static;
  209. bool staticB = bodyB.GetType() == BodyType.Static;
  210. // If the joint prevents collisions, then flag any contacts for filtering.
  211. if (def.collideConnected == false)
  212. {
  213. ContactEdge edge = bodyB.GetContactList();
  214. while (edge != null)
  215. {
  216. if (edge.Other == bodyA)
  217. {
  218. // Flag the contact for filtering at the next time step (where either
  219. // body is awake).
  220. edge.Contact.FlagForFiltering();
  221. }
  222. edge = edge.Next;
  223. }
  224. }
  225. // Note: creating a joint doesn't wake the bodies.
  226. return j;
  227. }
  228. /// Destroy a joint. This may cause the connected bodies to begin colliding.
  229. /// @warning This function is locked during callbacks.
  230. public void DestroyJoint(Joint j)
  231. {
  232. Debug.Assert(!IsLocked);
  233. if (IsLocked)
  234. {
  235. return;
  236. }
  237. bool collideConnected = j._collideConnected;
  238. // Remove from the doubly linked list.
  239. if (j._prev != null)
  240. {
  241. j._prev._next = j._next;
  242. }
  243. if (j._next != null)
  244. {
  245. j._next._prev = j._prev;
  246. }
  247. if (j == _jointList)
  248. {
  249. _jointList = j._next;
  250. }
  251. // Disconnect from island graph.
  252. Body bodyA = j._bodyA;
  253. Body bodyB = j._bodyB;
  254. // Wake up connected bodies.
  255. bodyA.SetAwake(true);
  256. bodyB.SetAwake(true);
  257. // Remove from body 1.
  258. if (j._edgeA.Prev != null)
  259. {
  260. j._edgeA.Prev.Next = j._edgeA.Next;
  261. }
  262. if (j._edgeA.Next != null)
  263. {
  264. j._edgeA.Next.Prev = j._edgeA.Prev;
  265. }
  266. if (j._edgeA == bodyA._jointList)
  267. {
  268. bodyA._jointList = j._edgeA.Next;
  269. }
  270. j._edgeA.Prev = null;
  271. j._edgeA.Next = null;
  272. // Remove from body 2
  273. if (j._edgeB.Prev != null)
  274. {
  275. j._edgeB.Prev.Next = j._edgeB.Next;
  276. }
  277. if (j._edgeB.Next != null)
  278. {
  279. j._edgeB.Next.Prev = j._edgeB.Prev;
  280. }
  281. if (j._edgeB == bodyB._jointList)
  282. {
  283. bodyB._jointList = j._edgeB.Next;
  284. }
  285. j._edgeB.Prev = null;
  286. j._edgeB.Next = null;
  287. Debug.Assert(_jointCount > 0);
  288. --_jointCount;
  289. // If the joint prevents collisions, then flag any contacts for filtering.
  290. if (collideConnected == false)
  291. {
  292. ContactEdge edge = bodyB.GetContactList();
  293. while (edge != null)
  294. {
  295. if (edge.Other == bodyA)
  296. {
  297. // Flag the contact for filtering at the next time step (where either
  298. // body is awake).
  299. edge.Contact.FlagForFiltering();
  300. }
  301. edge = edge.Next;
  302. }
  303. }
  304. }
  305. /// Take a time step. This performs collision detection, integration,
  306. /// and raint solution.
  307. /// @param timeStep the amount of time to simulate, this should not vary.
  308. /// @param velocityIterations for the velocity raint solver.
  309. /// @param positionIterations for the position raint solver.
  310. public void Step(float dt, int velocityIterations, int positionIterations)
  311. {
  312. // If new fixtures were added, we need to find the new contacts.
  313. if ((_flags & WorldFlags.NewFixture) == WorldFlags.NewFixture)
  314. {
  315. _contactManager.FindNewContacts();
  316. _flags &= ~WorldFlags.NewFixture;
  317. }
  318. _flags |= WorldFlags.Locked;
  319. TimeStep step;
  320. step.dt = dt;
  321. step.velocityIterations = velocityIterations;
  322. step.positionIterations = positionIterations;
  323. if (dt > 0.0f)
  324. {
  325. step.inv_dt = 1.0f / dt;
  326. }
  327. else
  328. {
  329. step.inv_dt = 0.0f;
  330. }
  331. step.dtRatio = _inv_dt0 * dt;
  332. step.warmStarting = WarmStarting;
  333. // Update contacts. This is where some contacts are destroyed.
  334. _contactManager.Collide();
  335. // Integrate velocities, solve velocity raints, and integrate positions.
  336. if (step.dt > 0.0f)
  337. {
  338. Solve(ref step);
  339. }
  340. // Handle TOI events.
  341. if (ContinuousPhysics && step.dt > 0.0f)
  342. {
  343. SolveTOI();
  344. }
  345. if (step.dt > 0.0f)
  346. {
  347. _inv_dt0 = step.inv_dt;
  348. }
  349. if ((_flags & WorldFlags.ClearForces) != 0)
  350. {
  351. ClearForces();
  352. }
  353. _flags &= ~WorldFlags.Locked;
  354. }
  355. /// Call this after you are done with time steps to clear the forces. You normally
  356. /// call this after each call to Step, unless you are performing sub-steps. By default,
  357. /// forces will be automatically cleared, so you don't need to call this function.
  358. /// @see SetAutoClearForces
  359. public void ClearForces()
  360. {
  361. for (Body body = _bodyList; body != null; body = body.GetNext())
  362. {
  363. body._force = Vector2.Zero;
  364. body._torque = 0.0f;
  365. }
  366. }
  367. /// Set flag to control automatic clearing of forces after each time step.
  368. void SetAutoClearForces(bool flag)
  369. {
  370. if (flag)
  371. {
  372. _flags |= WorldFlags.ClearForces;
  373. }
  374. else
  375. {
  376. _flags &= ~WorldFlags.ClearForces;
  377. }
  378. }
  379. /// Get the flag that controls automatic clearing of forces after each time step.
  380. bool GetAutoClearForces()
  381. {
  382. return (_flags & WorldFlags.ClearForces) == WorldFlags.ClearForces;
  383. }
  384. /// Get the contact manager for testing.
  385. public ContactManager GetContactManager()
  386. {
  387. return _contactManager;
  388. }
  389. /// Call this to draw shapes and other debug draw data.
  390. public void DrawDebugData()
  391. {
  392. if (DebugDraw == null)
  393. {
  394. return;
  395. }
  396. DebugDrawFlags flags = DebugDraw.Flags;
  397. if ((flags & DebugDrawFlags.Shape) == DebugDrawFlags.Shape)
  398. {
  399. for (Body b = _bodyList; b != null; b = b.GetNext())
  400. {
  401. Transform xf;
  402. b.GetTransform(out xf);
  403. for (Fixture f = b.GetFixtureList(); f != null; f = f.GetNext())
  404. {
  405. if (b.IsActive() == false)
  406. {
  407. DrawShape(f, xf, new Color(0.5f, 0.5f, 0.3f));
  408. }
  409. else if (b.GetType() == BodyType.Static)
  410. {
  411. DrawShape(f, xf, new Color(0.5f, 0.9f, 0.5f));
  412. }
  413. else if (b.GetType() == BodyType.Kinematic)
  414. {
  415. DrawShape(f, xf, new Color(0.5f, 0.5f, 0.9f));
  416. }
  417. else if (b.IsAwake() == false)
  418. {
  419. DrawShape(f, xf, new Color(0.6f, 0.6f, 0.6f));
  420. }
  421. else
  422. {
  423. DrawShape(f, xf, new Color(0.9f, 0.7f, 0.7f));
  424. }
  425. }
  426. }
  427. }
  428. if ((flags & DebugDrawFlags.Joint) == DebugDrawFlags.Joint)
  429. {
  430. for (Joint j = _jointList; j != null; j = j.GetNext())
  431. {
  432. DrawJoint(j);
  433. }
  434. }
  435. if ((flags & DebugDrawFlags.Pair) == DebugDrawFlags.Pair)
  436. {
  437. Color color = new Color(0.3f, 0.9f, 0.9f);
  438. for (Contact c = _contactManager._contactList; c != null; c = c.GetNext())
  439. {
  440. /*
  441. Fixture fixtureA = c.GetFixtureA();
  442. Fixture fixtureB = c.GetFixtureB();
  443. AABB aabbA;
  444. AABB aabbB;
  445. fixtureA.GetAABB(out aabbA);
  446. fixtureB.GetAABB(out aabbB);
  447. Vector2 cA = aabbA.GetCenter();
  448. Vector2 cB = aabbB.GetCenter();
  449. DebugDraw.DrawSegment(cA, cB, color);
  450. */
  451. }
  452. }
  453. if ((flags & DebugDrawFlags.AABB) == DebugDrawFlags.AABB)
  454. {
  455. Color color = new Color(0.9f, 0.3f, 0.9f);
  456. BroadPhase bp = _contactManager._broadPhase;
  457. for (Body b = _bodyList; b != null; b = b.GetNext())
  458. {
  459. if (b.IsActive() == false)
  460. {
  461. continue;
  462. }
  463. for (Fixture f = b.GetFixtureList(); f != null; f = f.GetNext())
  464. {
  465. for (int i = 0; i < f._proxyCount; ++i)
  466. {
  467. FixtureProxy proxy = f._proxies[i];
  468. AABB aabb;
  469. bp.GetFatAABB(proxy.proxyId, out aabb);
  470. FixedArray8<Vector2> vs = new FixedArray8<Vector2>();
  471. vs[0] = new Vector2(aabb.lowerBound.X, aabb.lowerBound.Y);
  472. vs[1] = new Vector2(aabb.upperBound.X, aabb.lowerBound.Y);
  473. vs[2] = new Vector2(aabb.upperBound.X, aabb.upperBound.Y);
  474. vs[3] = new Vector2(aabb.lowerBound.X, aabb.upperBound.Y);
  475. DebugDraw.DrawPolygon(ref vs, 4, color);
  476. }
  477. }
  478. }
  479. }
  480. if ((flags & DebugDrawFlags.CenterOfMass) == DebugDrawFlags.CenterOfMass)
  481. {
  482. for (Body b = _bodyList; b != null; b = b.GetNext())
  483. {
  484. Transform xf;
  485. b.GetTransform(out xf);
  486. xf.Position = b.GetWorldCenter();
  487. DebugDraw.DrawTransform(ref xf);
  488. }
  489. }
  490. }
  491. /// Query the world for all fixtures that potentially overlap the
  492. /// provided AABB.
  493. /// @param callback a user implemented callback class.
  494. /// @param aabb the query box.
  495. public void QueryAABB(Func<FixtureProxy, bool> callback, ref AABB aabb)
  496. {
  497. _queryAABBCallback = callback;
  498. _contactManager._broadPhase.Query(_queryAABBCallbackWrapper, ref aabb);
  499. _queryAABBCallback = null;
  500. }
  501. Func<FixtureProxy, bool> _queryAABBCallback;
  502. Func<int, bool> _queryAABBCallbackWrapper;
  503. bool QueryAABBCallbackWrapper(int proxyId)
  504. {
  505. FixtureProxy proxy = (FixtureProxy)_contactManager._broadPhase.GetUserData(proxyId);
  506. return _queryAABBCallback(proxy);
  507. }
  508. /// Ray-cast the world for all fixtures in the path of the ray. Your callback
  509. /// controls whether you get the closest point, any point, or n-points.
  510. /// The ray-cast ignores shapes that contain the starting point.
  511. /// @param callback a user implemented callback class.
  512. /// @param point1 the ray starting point
  513. /// @param point2 the ray ending point
  514. public void RayCast(RayCastCallback callback, Vector2 point1, Vector2 point2)
  515. {
  516. RayCastInput input = new RayCastInput();
  517. input.maxFraction = 1.0f;
  518. input.p1 = point1;
  519. input.p2 = point2;
  520. _rayCastCallback = callback;
  521. _contactManager._broadPhase.RayCast(_rayCastCallbackWrapper, ref input);
  522. _rayCastCallback = null;
  523. }
  524. RayCastCallback _rayCastCallback;
  525. RayCastCallbackInternal _rayCastCallbackWrapper;
  526. float RayCastCallbackWrapper(ref RayCastInput input, int proxyId)
  527. {
  528. object userData = _contactManager._broadPhase.GetUserData(proxyId);
  529. FixtureProxy proxy = (FixtureProxy)userData;
  530. Fixture fixture = proxy.fixture;
  531. int index = proxy.childIndex;
  532. RayCastOutput output;
  533. bool hit = fixture.RayCast(out output, ref input, index);
  534. if (hit)
  535. {
  536. float fraction = output.fraction;
  537. Vector2 point = (1.0f - fraction) * input.p1 + fraction * input.p2;
  538. return _rayCastCallback(fixture, point, output.normal, fraction);
  539. }
  540. return input.maxFraction;
  541. }
  542. /// Get the world body list. With the returned body, use Body.GetNext to get
  543. /// the next body in the world list. A null body indicates the end of the list.
  544. /// @return the head of the world body list.
  545. public Body GetBodyList()
  546. {
  547. return _bodyList;
  548. }
  549. /// Get the world joint list. With the returned joint, use Joint.GetNext to get
  550. /// the next joint in the world list. A null joint indicates the end of the list.
  551. /// @return the head of the world joint list.
  552. public Joint GetJointList()
  553. {
  554. return _jointList;
  555. }
  556. /// Get the world contact list. With the returned contact, use Contact.GetNext to get
  557. /// the next contact in the world list. A null contact indicates the end of the list.
  558. /// @return the head of the world contact list.
  559. /// @warning contacts are
  560. public Contact GetContactList()
  561. {
  562. return _contactManager._contactList;
  563. }
  564. /// Enable/disable warm starting. For testing.
  565. public bool WarmStarting { get; set; }
  566. /// Enable/disable continuous physics. For testing.
  567. public bool ContinuousPhysics { get; set; }
  568. /// Get the number of broad-phase proxies.
  569. public int ProxyCount
  570. {
  571. get
  572. {
  573. return _contactManager._broadPhase.ProxyCount;
  574. }
  575. }
  576. /// Get the number of bodies.
  577. public int BodyCount
  578. {
  579. get
  580. {
  581. return _bodyCount;
  582. }
  583. }
  584. /// Get the number of joints.
  585. public int JointCount
  586. {
  587. get
  588. {
  589. return _jointCount;
  590. }
  591. }
  592. /// Get the number of contacts (each may have 0 or more contact points).
  593. public int ContactCount
  594. {
  595. get
  596. {
  597. return _contactManager._contactCount;
  598. }
  599. }
  600. /// Change the global gravity vector.
  601. public Vector2 Gravity { get; set; }
  602. /// Is the world locked (in the middle of a time step).
  603. public bool IsLocked
  604. {
  605. get
  606. {
  607. return (_flags & WorldFlags.Locked) == WorldFlags.Locked;
  608. }
  609. set
  610. {
  611. if (value)
  612. {
  613. _flags |= WorldFlags.Locked;
  614. }
  615. else
  616. {
  617. _flags &= ~WorldFlags.Locked;
  618. }
  619. }
  620. }
  621. void Solve(ref TimeStep step)
  622. {
  623. // Size the island for the worst case.
  624. _island.Reset(_bodyCount,
  625. _contactManager._contactCount,
  626. _jointCount,
  627. _contactManager.ContactListener);
  628. // Clear all the island flags.
  629. for (Body b = _bodyList; b != null; b = b._next)
  630. {
  631. b._flags &= ~BodyFlags.Island;
  632. }
  633. for (Contact c = _contactManager._contactList; c != null; c = c._next)
  634. {
  635. c._flags &= ~ContactFlags.Island;
  636. }
  637. for (Joint j = _jointList; j != null; j = j._next)
  638. {
  639. j._islandFlag = false;
  640. }
  641. // Build and simulate all awake islands.
  642. int stackSize = _bodyCount;
  643. if (stackSize > stack.Length)
  644. stack = new Body[Math.Max(stack.Length * 2, stackSize)];
  645. for (Body seed = _bodyList; seed != null; seed = seed._next)
  646. {
  647. if ((seed._flags & (BodyFlags.Island)) != BodyFlags.None)
  648. {
  649. continue;
  650. }
  651. if (seed.IsAwake() == false || seed.IsActive() == false)
  652. {
  653. continue;
  654. }
  655. // The seed can be dynamic or kinematic.
  656. if (seed.GetType() == BodyType.Static)
  657. {
  658. continue;
  659. }
  660. // Reset island and stack.
  661. _island.Clear();
  662. int stackCount = 0;
  663. stack[stackCount++] = seed;
  664. seed._flags |= BodyFlags.Island;
  665. // Perform a depth first search (DFS) on the raint graph.
  666. while (stackCount > 0)
  667. {
  668. // Grab the next body off the stack and add it to the island.
  669. Body b = stack[--stackCount];
  670. Debug.Assert(b.IsActive() == true);
  671. _island.Add(b);
  672. // Make sure the body is awake.
  673. b.SetAwake(true);
  674. // To keep islands as small as possible, we don't
  675. // propagate islands across static bodies.
  676. if (b.GetType() == BodyType.Static)
  677. {
  678. continue;
  679. }
  680. // Search all contacts connected to this body.
  681. for (ContactEdge ce = b._contactList; ce != null; ce = ce.Next)
  682. {
  683. Contact contact = ce.Contact;
  684. // Has this contact already been added to an island?
  685. if ((contact._flags & ContactFlags.Island) != ContactFlags.None)
  686. {
  687. continue;
  688. }
  689. // Is this contact solid and touching?
  690. if (!ce.Contact.IsEnabled() || !ce.Contact.IsTouching())
  691. {
  692. continue;
  693. }
  694. // Skip sensors.
  695. bool sensorA = contact._fixtureA._isSensor;
  696. bool sensorB = contact._fixtureB._isSensor;
  697. if (sensorA || sensorB)
  698. {
  699. continue;
  700. }
  701. _island.Add(contact);
  702. contact._flags |= ContactFlags.Island;
  703. Body other = ce.Other;
  704. // Was the other body already added to this island?
  705. if ((other._flags & BodyFlags.Island) != BodyFlags.None)
  706. {
  707. continue;
  708. }
  709. Debug.Assert(stackCount < stackSize);
  710. stack[stackCount++] = other;
  711. other._flags |= BodyFlags.Island;
  712. }
  713. // Search all joints connect to this body.
  714. for (JointEdge je = b._jointList; je != null; je = je.Next)
  715. {
  716. if (je.Joint._islandFlag == true)
  717. {
  718. continue;
  719. }
  720. Body other = je.Other;
  721. // Don't simulate joints connected to inactive bodies.
  722. if (other.IsActive() == false)
  723. {
  724. continue;
  725. }
  726. _island.Add(je.Joint);
  727. je.Joint._islandFlag = true;
  728. if ((other._flags & BodyFlags.Island) != BodyFlags.None)
  729. {
  730. continue;
  731. }
  732. Debug.Assert(stackCount < stackSize);
  733. stack[stackCount++] = other;
  734. other._flags |= BodyFlags.Island;
  735. }
  736. }
  737. _island.Solve(ref step, Gravity, _allowSleep);
  738. // Post solve cleanup.
  739. for (int i = 0; i < _island._bodyCount; ++i)
  740. {
  741. // Allow static bodies to participate in other islands.
  742. Body b = _island._bodies[i];
  743. if (b.GetType() == BodyType.Static)
  744. {
  745. b._flags &= ~BodyFlags.Island;
  746. }
  747. }
  748. }
  749. // Synchronize fixtures, check for out of range bodies.
  750. for (Body b = _bodyList; b != null; b = b.GetNext())
  751. {
  752. // If a body was not in an island then it did not move.
  753. if ((b._flags & BodyFlags.Island) != BodyFlags.Island)
  754. {
  755. continue;
  756. }
  757. if (b.GetType() == BodyType.Static)
  758. {
  759. continue;
  760. }
  761. // Update fixtures (for broad-phase).
  762. b.SynchronizeFixtures();
  763. }
  764. // Look for new contacts.
  765. _contactManager.FindNewContacts();
  766. }
  767. // Advance a dynamic body to its first time of contact
  768. // and adjust the position to ensure clearance.
  769. void SolveTOI(Body body)
  770. {
  771. // Find the minimum contact.
  772. Contact toiContact = null;
  773. float toi = 1.0f;
  774. Body toiOther = null;
  775. bool found;
  776. int count;
  777. int iter = 0;
  778. bool bullet = body.IsBullet;
  779. // Iterate until all contacts agree on the minimum TOI. We have
  780. // to iterate because the TOI algorithm may skip some intermediate
  781. // collisions when objects rotate through each other.
  782. do
  783. {
  784. count = 0;
  785. found = false;
  786. for (ContactEdge ce = body._contactList; ce != null; ce = ce.Next)
  787. {
  788. if (ce.Contact == toiContact)
  789. {
  790. continue;
  791. }
  792. Body other = ce.Other;
  793. BodyType type = other.GetType();
  794. // Only bullets perform TOI with dynamic bodies.
  795. if (bullet == true)
  796. {
  797. // Bullets only perform TOI with bodies that have their TOI resolved.
  798. if ((other._flags & BodyFlags.Toi) == 0)
  799. {
  800. continue;
  801. }
  802. // No repeated hits on non-static bodies
  803. if (type != BodyType.Static && (ce.Contact._flags & ContactFlags.BulletHit) != 0)
  804. {
  805. continue;
  806. }
  807. }
  808. else if (type == BodyType.Dynamic)
  809. {
  810. continue;
  811. }
  812. // Check for a disabled contact.
  813. Contact contact = ce.Contact;
  814. if (contact.IsEnabled() == false)
  815. {
  816. continue;
  817. }
  818. // Prevent infinite looping.
  819. if (contact._toiCount > 10)
  820. {
  821. continue;
  822. }
  823. Fixture fixtureA = contact._fixtureA;
  824. Fixture fixtureB = contact._fixtureB;
  825. int indexA = contact._indexA;
  826. int indexB = contact._indexB;
  827. // Cull sensors.
  828. if (fixtureA.IsSensor() || fixtureB.IsSensor())
  829. {
  830. continue;
  831. }
  832. Body bodyA = fixtureA._body;
  833. Body bodyB = fixtureB._body;
  834. // Compute the time of impact in interval [0, minTOI]
  835. TOIInput input = new TOIInput();
  836. input.proxyA.Set(fixtureA.GetShape(), indexA);
  837. input.proxyB.Set(fixtureB.GetShape(), indexB);
  838. input.sweepA = bodyA._sweep;
  839. input.sweepB = bodyB._sweep;
  840. input.tMax = toi;
  841. TOIOutput output;
  842. TimeOfImpact.CalculateTimeOfImpact(out output, ref input);
  843. if (output.State == TOIOutputState.Touching && output.t < toi)
  844. {
  845. toiContact = contact;
  846. toi = output.t;
  847. toiOther = other;
  848. found = true;
  849. }
  850. ++count;
  851. }
  852. ++iter;
  853. } while (found && count > 1 && iter < 50);
  854. if (toiContact == null)
  855. {
  856. body.Advance(1.0f);
  857. return;
  858. }
  859. Sweep backup = body._sweep;
  860. body.Advance(toi);
  861. toiContact.Update(_contactManager.ContactListener);
  862. if (toiContact.IsEnabled() == false)
  863. {
  864. // Contact disabled. Backup and recurse.
  865. body._sweep = backup;
  866. SolveTOI(body);
  867. }
  868. ++toiContact._toiCount;
  869. // Update all the valid contacts on this body and build a contact island.
  870. count = 0;
  871. for (ContactEdge ce = body._contactList; (ce != null) && (count < Settings.b2_maxTOIContacts); ce = ce.Next)
  872. {
  873. Body other = ce.Other;
  874. BodyType type = other.GetType();
  875. // Only perform correction with static bodies, so the
  876. // body won't get pushed out of the world.
  877. if (type == BodyType.Dynamic)
  878. {
  879. continue;
  880. }
  881. // Check for a disabled contact.
  882. Contact contact = ce.Contact;
  883. if (contact.IsEnabled() == false)
  884. {
  885. continue;
  886. }
  887. Fixture fixtureA = contact._fixtureA;
  888. Fixture fixtureB = contact._fixtureB;
  889. // Cull sensors.
  890. if (fixtureA.IsSensor() || fixtureB.IsSensor())
  891. {
  892. continue;
  893. }
  894. // The contact likely has some new contact points. The listener
  895. // gives the user a chance to disable the contact.
  896. if (contact != toiContact)
  897. {
  898. contact.Update(_contactManager.ContactListener);
  899. }
  900. // Did the user disable the contact?
  901. if (contact.IsEnabled() == false)
  902. {
  903. // Skip this contact.
  904. continue;
  905. }
  906. if (contact.IsTouching() == false)
  907. {
  908. continue;
  909. }
  910. _toiContacts[count] = contact;
  911. ++count;
  912. }
  913. // Reduce the TOI body's overlap with the contact island.
  914. _toiSolver.Initialize(_toiContacts, count, body);
  915. float k_toiBaumgarte = 0.75f;
  916. //bool solved = false;
  917. for (int i = 0; i < 20; ++i)
  918. {
  919. bool contactsOkay = _toiSolver.Solve(k_toiBaumgarte);
  920. if (contactsOkay)
  921. {
  922. //solved = true;
  923. break;
  924. }
  925. }
  926. if (toiOther.GetType() != BodyType.Static)
  927. {
  928. toiContact._flags |= ContactFlags.BulletHit;
  929. }
  930. }
  931. // Sequentially solve TOIs for each body. We bring each
  932. // body to the time of contact and perform some position correction.
  933. // Time is not conserved.
  934. void SolveTOI()
  935. {
  936. // Prepare all contacts.
  937. for (Contact c = _contactManager._contactList; c != null; c = c._next)
  938. {
  939. // Enable the contact
  940. c._flags |= ContactFlags.Enabled;
  941. // Set the number of TOI events for this contact to zero.
  942. c._toiCount = 0;
  943. }
  944. // Initialize the TOI flag.
  945. for (Body body = _bodyList; body != null; body = body._next)
  946. {
  947. // Kinematic, and static bodies will not be affected by the TOI event.
  948. // If a body was not in an island then it did not move.
  949. if ((body._flags & BodyFlags.Island) == 0 || body.GetType() == BodyType.Kinematic || body.GetType() == BodyType.Static)
  950. {
  951. body._flags |= BodyFlags.Toi;
  952. }
  953. else
  954. {
  955. body._flags &= ~BodyFlags.Toi;
  956. }
  957. }
  958. // Collide non-bullets.
  959. for (Body body = _bodyList; body != null; body = body._next)
  960. {
  961. if ((body._flags & BodyFlags.Toi) != BodyFlags.None)
  962. {
  963. continue;
  964. }
  965. if (body.IsBullet == true)
  966. {
  967. continue;
  968. }
  969. SolveTOI(body);
  970. body._flags |= BodyFlags.Toi;
  971. }
  972. // Collide bullets.
  973. for (Body body = _bodyList; body != null; body = body._next)
  974. {
  975. if ((body._flags & BodyFlags.Toi) != BodyFlags.None)
  976. {
  977. continue;
  978. }
  979. if (body.IsBullet == false)
  980. {
  981. continue;
  982. }
  983. SolveTOI(body);
  984. body._flags |= BodyFlags.Toi;
  985. }
  986. }
  987. void DrawJoint(Joint joint)
  988. {
  989. Body b1 = joint.GetBodyA();
  990. Body b2 = joint.GetBodyB();
  991. Transform xf1, xf2;
  992. b1.GetTransform(out xf1);
  993. b2.GetTransform(out xf2);
  994. Vector2 x1 = xf1.Position;
  995. Vector2 x2 = xf2.Position;
  996. Vector2 p1 = joint.GetAnchorA();
  997. Vector2 p2 = joint.GetAnchorB();
  998. Color color = new Color(0.5f, 0.8f, 0.8f);
  999. switch (joint.JointType)
  1000. {
  1001. case JointType.Distance:
  1002. DebugDraw.DrawSegment(p1, p2, color);
  1003. break;
  1004. case JointType.Pulley:
  1005. {
  1006. PulleyJoint pulley = (PulleyJoint)joint;
  1007. Vector2 s1 = pulley.GetGroundAnchorA();
  1008. Vector2 s2 = pulley.GetGroundAnchorB();
  1009. DebugDraw.DrawSegment(s1, p1, color);
  1010. DebugDraw.DrawSegment(s2, p2, color);
  1011. DebugDraw.DrawSegment(s1, s2, color);
  1012. }
  1013. break;
  1014. case JointType.Mouse:
  1015. // don't draw this
  1016. break;
  1017. default:
  1018. DebugDraw.DrawSegment(x1, p1, color);
  1019. DebugDraw.DrawSegment(p1, p2, color);
  1020. DebugDraw.DrawSegment(x2, p2, color);
  1021. break;
  1022. }
  1023. }
  1024. void DrawShape(Fixture fixture, Transform xf, Color color)
  1025. {
  1026. switch (fixture.ShapeType)
  1027. {
  1028. case ShapeType.Circle:
  1029. {
  1030. CircleShape circle = (CircleShape)fixture.GetShape();
  1031. Vector2 center = MathUtils.Multiply(ref xf, circle._p);
  1032. float radius = circle._radius;
  1033. Vector2 axis = xf.R.col1;
  1034. DebugDraw.DrawSolidCircle(center, radius, axis, color);
  1035. }
  1036. break;
  1037. case ShapeType.Polygon:
  1038. {
  1039. PolygonShape poly = (PolygonShape)fixture.GetShape();
  1040. int vertexCount = poly._vertexCount;
  1041. Debug.Assert(vertexCount <= Settings.b2_maxPolygonVertices);
  1042. FixedArray8<Vector2> vertices = new FixedArray8<Vector2>();
  1043. for (int i = 0; i < vertexCount; ++i)
  1044. {
  1045. vertices[i] = MathUtils.Multiply(ref xf, poly._vertices[i]);
  1046. }
  1047. DebugDraw.DrawSolidPolygon(ref vertices, vertexCount, color);
  1048. }
  1049. break;
  1050. case ShapeType.Edge:
  1051. {
  1052. EdgeShape edge = (EdgeShape)fixture.GetShape();
  1053. Vector2 v1 = MathUtils.Multiply(ref xf, edge._vertex1);
  1054. Vector2 v2 = MathUtils.Multiply(ref xf, edge._vertex2);
  1055. DebugDraw.DrawSegment(v1, v2, color);
  1056. }
  1057. break;
  1058. case ShapeType.Loop:
  1059. {
  1060. LoopShape loop = (LoopShape)fixture.GetShape();
  1061. int count = loop._count;
  1062. Vector2 v1 = MathUtils.Multiply(ref xf, loop._vertices[count - 1]);
  1063. for (int i = 0; i < count; ++i)
  1064. {
  1065. Vector2 v2 = MathUtils.Multiply(ref xf, loop._vertices[i]);
  1066. DebugDraw.DrawSegment(v1, v2, color);
  1067. v1 = v2;
  1068. }
  1069. }
  1070. break;
  1071. }
  1072. }
  1073. TOISolver _toiSolver = new TOISolver();
  1074. Contact[] _toiContacts = new Contact[Settings.b2_maxTOIContacts];
  1075. internal Island _island = new Island();
  1076. internal WorldFlags _flags;
  1077. internal ContactManager _contactManager = new ContactManager();
  1078. internal Queue<Contact> _contactPool = new Queue<Contact>(256);
  1079. internal Body _bodyList;
  1080. internal Joint _jointList;
  1081. internal int _bodyCount;
  1082. internal int _jointCount;
  1083. internal bool _allowSleep;
  1084. internal Body _groundBody;
  1085. // This is used to compute the time step ratio to
  1086. // support a variable time step.
  1087. internal float _inv_dt0;
  1088. Body[] stack = new Body[64];
  1089. }
  1090. }