World.hpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2011 Erin Catto http://www.box2d.org
3  * Modified work Copyright (c) 2017 Louis Langholtz https://github.com/louis-langholtz/PlayRho
4  *
5  * This software is provided 'as-is', without any express or implied
6  * warranty. In no event will the authors be held liable for any damages
7  * arising from the use of this software.
8  *
9  * Permission is granted to anyone to use this software for any purpose,
10  * including commercial applications, and to alter it and redistribute it
11  * freely, subject to the following restrictions:
12  *
13  * 1. The origin of this software must not be misrepresented; you must not
14  * claim that you wrote the original software. If you use this software
15  * in a product, an acknowledgment in the product documentation would be
16  * appreciated but is not required.
17  * 2. Altered source versions must be plainly marked as such, and must not be
18  * misrepresented as being the original software.
19  * 3. This notice may not be removed or altered from any source distribution.
20  */
21 
22 #ifndef PLAYRHO_DYNAMICS_WORLD_HPP
23 #define PLAYRHO_DYNAMICS_WORLD_HPP
24 
27 
28 #include <PlayRho/Common/Math.hpp>
29 #include <PlayRho/Common/Range.hpp>
41 
42 #include <iterator>
43 #include <vector>
44 #include <map>
45 #include <unordered_set>
46 #include <memory>
47 #include <stdexcept>
48 #include <functional>
49 
50 namespace playrho {
51 
52 class StepConf;
53 enum class BodyType;
54 
55 namespace d2 {
56 
57 struct BodyConf;
58 struct JointConf;
59 struct FixtureConf;
60 class Body;
61 class Contact;
62 class Fixture;
63 class Joint;
64 struct Island;
65 class Shape;
66 struct ShapeConf;
67 
89 
115 class World
116 {
117 public:
119  using Bodies = std::vector<Body*>;
120 
122  using Contacts = std::vector<KeyedContactPtr>;
123 
126  using Joints = std::vector<Joint*>;
127 
129  using Fixtures = std::vector<Fixture*>;
130 
137  explicit World(const WorldConf& def = GetDefaultWorldConf());
138 
144  World(const World& other);
145 
153  World& operator= (const World& other);
154 
158  ~World() noexcept;
159 
164  void Clear();
165 
168  void SetDestructionListener(DestructionListener* listener) noexcept;
169 
172  void SetContactListener(ContactListener* listener) noexcept;
173 
187  Body* CreateBody(const BodyConf& def = GetDefaultBodyConf());
188 
201  Joint* CreateJoint(const JointConf& def);
202 
219  void Destroy(Body* body);
220 
233  void Destroy(Joint* joint);
234 
273  StepStats Step(const StepConf& conf);
274 
282  SizedRange<Bodies::iterator> GetBodies() noexcept;
283 
291  SizedRange<Bodies::const_iterator> GetBodies() const noexcept;
292 
297  SizedRange<Bodies::const_iterator> GetBodiesForProxies() const noexcept;
298 
303  SizedRange<Fixtures::const_iterator> GetFixturesForProxies() const noexcept;
304 
311  SizedRange<Joints::const_iterator> GetJoints() const noexcept;
312 
319  SizedRange<Joints::iterator> GetJoints() noexcept;
320 
325  SizedRange<Contacts::const_iterator> GetContacts() const noexcept;
326 
332  bool IsStepComplete() const noexcept;
333 
335  bool GetSubStepping() const noexcept;
336 
342  void SetSubStepping(bool flag) noexcept;
343 
345  const DynamicTree& GetTree() const noexcept;
346 
348  bool IsLocked() const noexcept;
349 
357  void ShiftOrigin(Length2 newOrigin);
358 
360  Length GetMinVertexRadius() const noexcept;
361 
363  Length GetMaxVertexRadius() const noexcept;
364 
369  Frequency GetInvDeltaTime() const noexcept;
370 
371 private:
372  friend class WorldAtty;
373 
377  void SetType(Body& body, playrho::BodyType type);
378 
381  void RegisterForProxies(Fixture& fixture);
382 
385  void UnregisterForProxies(const Fixture& fixture);
386 
389  void RegisterForProxies(Body& body);
390 
393  void UnregisterForProxies(const Body& body);
394 
402  Fixture* CreateFixture(Body& body, const Shape& shape,
403  const FixtureConf& def = GetDefaultFixtureConf(),
404  bool resetMassData = true);
405 
417  bool Destroy(Fixture& fixture, bool resetMassData = true);
418 
423  void TouchProxies(Fixture& fixture) noexcept;
424 
426  void SetNewFixtures() noexcept;
427 
429  using FlagsType = std::uint32_t;
430 
432  using ProxyId = DynamicTree::Size;
433 
435  using ContactKeyQueue = std::vector<ContactKey>;
436 
438  using ProxyQueue = std::vector<ProxyId>;
439 
441  enum Flag: FlagsType
442  {
444  e_newFixture = 0x0001,
445 
447  e_locked = 0x0002,
448 
450  e_substepping = 0x0020,
451 
453  e_stepComplete = 0x0040,
454  };
455 
457  void CopyBodies(std::map<const Body*, Body*>& bodyMap,
458  std::map<const Fixture*, Fixture*>& fixtureMap,
460 
462  void CopyJoints(const std::map<const Body*, Body*>& bodyMap,
464 
466  void CopyContacts(const std::map<const Body*, Body*>& bodyMap,
467  const std::map<const Fixture*, Fixture*>& fixtureMap,
469 
471  void InternalClear() noexcept;
472 
475  void InternalDestroy(Joint& joint) noexcept;
476 
481  RegStepStats SolveReg(const StepConf& conf);
482 
504  IslandStats SolveRegIslandViaGS(const StepConf& conf, Island island);
505 
509  void AddToIsland(Island& island, Body& seed,
510  Bodies::size_type& remNumBodies,
511  Contacts::size_type& remNumContacts,
512  Joints::size_type& remNumJoints);
513 
517  using BodyStack = std::vector<Body*>;
518 
520  void AddToIsland(Island& island, BodyStack& stack,
521  Bodies::size_type& remNumBodies,
522  Contacts::size_type& remNumContacts,
523  Joints::size_type& remNumJoints);
524 
526  void AddContactsToIsland(Island& island, BodyStack& stack, const Body* b);
527 
529  void AddJointsToIsland(Island& island, BodyStack& stack, const Body* b);
530 
532  Bodies::size_type RemoveUnspeedablesFromIslanded(const std::vector<Body*>& bodies);
533 
539  ToiStepStats SolveToi(const StepConf& conf);
540 
551  IslandStats SolveToi(const StepConf& conf, Contact& contact);
552 
573  IslandStats SolveToiViaGS(const StepConf& conf, Island& island);
574 
580  static void UpdateBody(Body& body, const Position& pos, const Velocity& vel);
581 
583  void ResetBodiesForSolveTOI() noexcept;
584 
586  void ResetContactsForSolveTOI() noexcept;
587 
589  void ResetContactsForSolveTOI(Body& body) noexcept;
590 
592  struct ProcessContactsOutput
593  {
594  ContactCounter contactsUpdated = 0;
595  ContactCounter contactsSkipped = 0;
596  };
597 
612  ProcessContactsOutput ProcessContactsForTOI(Island& island, Body& body, Real toi,
613  const StepConf& conf);
614 
617  bool Add(Joint* j);
618 
620  void Remove(const Body& b) noexcept;
621 
623  void Remove(const Joint& j) noexcept;
624 
626  void SetStepComplete(bool value) noexcept;
627 
629  void SetAllowSleeping() noexcept;
630 
632  void UnsetAllowSleeping() noexcept;
633 
635  struct UpdateContactsStats
636  {
638  ContactCounter ignored = 0;
639 
641  ContactCounter updated = 0;
642 
644  ContactCounter skipped = 0;
645  };
646 
648  struct DestroyContactsStats
649  {
650  ContactCounter ignored = 0;
651  ContactCounter erased = 0;
652  };
653 
655  struct ContactToiData
656  {
657  Contact* contact = nullptr;
658  Real toi = std::numeric_limits<Real>::infinity();
659  ContactCounter simultaneous = 0;
660  };
661 
663  struct UpdateContactsData
664  {
665  ContactCounter numAtMaxSubSteps = 0;
666  ContactCounter numUpdatedTOI = 0;
667  ContactCounter numValidTOI = 0;
668 
670  using dist_iter_type = std::remove_const<decltype(DefaultMaxDistanceIters)>::type;
671 
673  using toi_iter_type = std::remove_const<decltype(DefaultMaxToiIters)>::type;
674 
676  using root_iter_type = std::remove_const<decltype(DefaultMaxToiRootIters)>::type;
677 
678  dist_iter_type maxDistIters = 0;
679  toi_iter_type maxToiIters = 0;
680  root_iter_type maxRootIters = 0;
681  };
682 
684  UpdateContactsData UpdateContactTOIs(const StepConf& conf);
685 
690  ContactToiData GetSoonestContact() const noexcept;
691 
693  bool HasNewFixtures() const noexcept;
694 
696  void UnsetNewFixtures() noexcept;
697 
701  ContactCounter FindNewContacts();
702 
710  DestroyContactsStats DestroyContacts(Contacts& contacts);
711 
713  UpdateContactsStats UpdateContacts(Contacts& contacts, const StepConf& conf);
714 
720  void Destroy(Contact* contact, Body* from);
721 
736  bool Add(ContactKey key);
737 
739  void RegisterForProcessing(ProxyId pid) noexcept;
740 
742  void UnregisterForProcessing(ProxyId pid) noexcept;
743 
745  void InternalDestroy(Contact* contact, Body* from = nullptr);
746 
749  void CreateProxies(Fixture& fixture, Length aabbExtension);
750 
753  void DestroyProxies(Fixture& fixture) noexcept;
754 
757  void InternalTouchProxies(Fixture& fixture) noexcept;
758 
762  ContactCounter Synchronize(Body& body,
763  Transformation xfm1, Transformation xfm2,
764  Real multiplier, Length extension);
765 
769  ContactCounter Synchronize(Fixture& fixture,
770  Transformation xfm1, Transformation xfm2,
771  Length2 displacement, Length extension);
772 
774  void CreateAndDestroyProxies(const StepConf& conf);
775 
777  void CreateAndDestroyProxies(Fixture& fixture, const StepConf& conf);
778 
780  PreStepStats::counter_type SynchronizeProxies(const StepConf& conf);
781 
783  bool IsIslanded(const Body* body) const noexcept;
784 
786  bool IsIslanded(const Contact* contact) const noexcept;
787 
789  bool IsIslanded(const Joint* joint) const noexcept;
790 
792  void SetIslanded(Body* body) noexcept;
793 
795  void SetIslanded(Contact* contact) noexcept;
796 
798  void SetIslanded(Joint* joint) noexcept;
799 
801  void UnsetIslanded(Body* body) noexcept;
802 
804  void UnsetIslanded(Contact* contact) noexcept;
805 
807  void UnsetIslanded(Joint* joint) noexcept;
808 
809  /******** Member variables. ********/
810 
811  DynamicTree m_tree;
812 
813  ContactKeyQueue m_proxyKeys;
814  ProxyQueue m_proxies;
815  Fixtures m_fixturesForProxies;
816  Bodies m_bodiesForProxies;
817 
818  Bodies m_bodies;
819 
820  Joints m_joints;
821 
825  Contacts m_contacts;
826 
827  DestructionListener* m_destructionListener = nullptr;
828 
829  ContactListener* m_contactListener = nullptr;
830 
831  FlagsType m_flags = e_stepComplete;
832 
837  Frequency m_inv_dt0 = 0;
838 
840  Positive<Length> m_minVertexRadius;
841 
850  Positive<Length> m_maxVertexRadius;
851 };
852 
856 
860 
861 inline SizedRange<World::Bodies::iterator> World::GetBodies() noexcept
862 {
863  return {begin(m_bodies), end(m_bodies), size(m_bodies)};
864 }
865 
867 {
868  return {begin(m_bodies), end(m_bodies), size(m_bodies)};
869 }
870 
872 {
873  return {cbegin(m_bodiesForProxies), cend(m_bodiesForProxies), size(m_bodiesForProxies)};
874 }
875 
877 {
878  return {cbegin(m_fixturesForProxies), cend(m_fixturesForProxies), size(m_fixturesForProxies)};
879 }
880 
882 {
883  return {begin(m_joints), end(m_joints), size(m_joints)};
884 }
885 
887 {
888  return {begin(m_joints), end(m_joints), size(m_joints)};
889 }
890 
892 {
893  return {begin(m_contacts), end(m_contacts), size(m_contacts)};
894 }
895 
896 inline bool World::IsLocked() const noexcept
897 {
898  return (m_flags & e_locked) == e_locked;
899 }
900 
901 inline bool World::IsStepComplete() const noexcept
902 {
903  return (m_flags & e_stepComplete) != 0u;
904 }
905 
906 inline void World::SetStepComplete(bool value) noexcept
907 {
908  if (value)
909  {
910  m_flags |= e_stepComplete;
911  }
912  else
913  {
914  m_flags &= ~e_stepComplete;
915  }
916 }
917 
918 inline bool World::GetSubStepping() const noexcept
919 {
920  return (m_flags & e_substepping) != 0u;
921 }
922 
923 inline void World::SetSubStepping(bool flag) noexcept
924 {
925  if (flag)
926  {
927  m_flags |= e_substepping;
928  }
929  else
930  {
931  m_flags &= ~e_substepping;
932  }
933 }
934 
935 inline bool World::HasNewFixtures() const noexcept
936 {
937  return (m_flags & e_newFixture) != 0u;
938 }
939 
940 inline void World::SetNewFixtures() noexcept
941 {
942  m_flags |= e_newFixture;
943 }
944 
945 inline void World::UnsetNewFixtures() noexcept
946 {
947  m_flags &= ~e_newFixture;
948 }
949 
950 inline Length World::GetMinVertexRadius() const noexcept
951 {
952  return m_minVertexRadius;
953 }
954 
955 inline Length World::GetMaxVertexRadius() const noexcept
956 {
957  return m_maxVertexRadius;
958 }
959 
960 inline Frequency World::GetInvDeltaTime() const noexcept
961 {
962  return m_inv_dt0;
963 }
964 
965 inline const DynamicTree& World::GetTree() const noexcept
966 {
967  return m_tree;
968 }
969 
970 inline void World::SetDestructionListener(DestructionListener* listener) noexcept
971 {
972  m_destructionListener = listener;
973 }
974 
975 inline void World::SetContactListener(ContactListener* listener) noexcept
976 {
977  m_contactListener = listener;
978 }
979 
980 inline bool World::IsIslanded(const Body* body) const noexcept
981 {
982  return BodyAtty::IsIslanded(*body);
983 }
984 
985 inline bool World::IsIslanded(const Contact* contact) const noexcept
986 {
987  return ContactAtty::IsIslanded(*contact);
988 }
989 
990 inline bool World::IsIslanded(const Joint* joint) const noexcept
991 {
992  return JointAtty::IsIslanded(*joint);
993 }
994 
995 inline void World::SetIslanded(Body* body) noexcept
996 {
997  BodyAtty::SetIslanded(*body);
998 }
999 
1000 inline void World::SetIslanded(Contact* contact) noexcept
1001 {
1002  ContactAtty::SetIslanded(*contact);
1003 }
1004 
1005 inline void World::SetIslanded(Joint* joint) noexcept
1006 {
1007  JointAtty::SetIslanded(*joint);
1008 }
1009 
1010 inline void World::UnsetIslanded(Body* body) noexcept
1011 {
1012  BodyAtty::UnsetIslanded(*body);
1013 }
1014 
1015 inline void World::UnsetIslanded(Contact* contact) noexcept
1016 {
1017  ContactAtty::UnsetIslanded(*contact);
1018 }
1019 
1020 inline void World::UnsetIslanded(Joint* joint) noexcept
1021 {
1022  JointAtty::UnsetIslanded(*joint);
1023 }
1024 
1025 inline void World::RegisterForProcessing(ProxyId pid) noexcept
1026 {
1027  assert(pid != DynamicTree::GetInvalidSize());
1028  m_proxies.push_back(pid);
1029 }
1030 
1031 // Free functions.
1032 
1036 inline BodyCounter GetBodyCount(const World& world) noexcept
1037 {
1038  return static_cast<BodyCounter>(size(world.GetBodies()));
1039 }
1040 
1044 inline JointCounter GetJointCount(const World& world) noexcept
1045 {
1046  return static_cast<JointCounter>(size(world.GetJoints()));
1047 }
1048 
1054 inline ContactCounter GetContactCount(const World& world) noexcept
1055 {
1056  return static_cast<ContactCounter>(size(world.GetContacts()));
1057 }
1058 
1061 ContactCounter GetTouchingCount(const World& world) noexcept;
1062 
1094 StepStats Step(World& world, Time delta,
1095  TimestepIters velocityIterations = 8,
1096  TimestepIters positionIterations = 3);
1097 
1100 std::size_t GetFixtureCount(const World& world) noexcept;
1101 
1104 std::size_t GetShapeCount(const World& world) noexcept;
1105 
1108 BodyCounter GetAwakeCount(const World& world) noexcept;
1109 
1115 BodyCounter Awaken(World& world) noexcept;
1116 
1122 template <class F>
1123 void SetAccelerations(World& world, F fn) noexcept
1124 {
1125  const auto bodies = world.GetBodies();
1126  std::for_each(begin(bodies), end(bodies), [&](World::Bodies::value_type &b) {
1127  SetAcceleration(GetRef(b), fn(GetRef(b)));
1128  });
1129 }
1130 
1133 void SetAccelerations(World& world, Acceleration acceleration) noexcept;
1134 
1138 void SetAccelerations(World& world, LinearAcceleration2 acceleration) noexcept;
1139 
1143 inline void ClearForces(World& world) noexcept
1144 {
1146  LinearAcceleration2{0_mps2, 0_mps2}, 0 * RadianPerSquareSecond
1147  });
1148 }
1149 
1152 Body* FindClosestBody(const World& world, Length2 location) noexcept;
1153 
1154 } // namespace d2
1155 
1157 RegStepStats& Update(RegStepStats& lhs, const IslandStats& rhs) noexcept;
1158 
1159 } // namespace playrho
1160 
1161 #endif // PLAYRHO_DYNAMICS_WORLD_HPP