Joint.hpp
Go to the documentation of this file.
1 /*
2  * Original work Copyright (c) 2006-2007 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_JOINTS_JOINT_HPP
23 #define PLAYRHO_DYNAMICS_JOINTS_JOINT_HPP
24 
25 #include <PlayRho/Common/Math.hpp>
26 
27 #include <unordered_map>
28 #include <vector>
29 #include <utility>
30 #include <stdexcept>
31 
32 namespace playrho {
33 class StepConf;
34 struct ConstraintSolverConf;
35 
36 namespace d2 {
37 
38 class Body;
39 struct Velocity;
40 class BodyConstraint;
41 class JointVisitor;
42 struct JointConf;
43 
47 
50 
52 using BodyConstraintPair = std::pair<const Body*, BodyConstraintPtr>;
53 
54 // #define USE_VECTOR_MAP
55 
57 using BodyConstraintsMap =
58 #ifdef USE_VECTOR_MAP
59  std::vector<std::pair<const Body*, BodyConstraintPtr>>;
60 #else
61  std::unordered_map<const Body*, BodyConstraint*>;
62 #endif
63 
74 class Joint
75 {
76 public:
77 
81  {
84 
87 
90 
95  };
96 
98  static bool IsOkay(const JointConf& def) noexcept;
99 
100  virtual ~Joint() noexcept = default;
101 
103  Body* GetBodyA() const noexcept;
104 
106  Body* GetBodyB() const noexcept;
107 
109  virtual Length2 GetAnchorA() const = 0;
110 
112  virtual Length2 GetAnchorB() const = 0;
113 
115  virtual Momentum2 GetLinearReaction() const = 0;
116 
118  virtual AngularMomentum GetAngularReaction() const = 0;
119 
125  virtual void Accept(JointVisitor& visitor) const = 0;
126 
132  virtual void Accept(JointVisitor& visitor) = 0;
133 
135  void* GetUserData() const noexcept;
136 
138  void SetUserData(void* data) noexcept;
139 
143  bool GetCollideConnected() const noexcept;
144 
147  virtual bool ShiftOrigin(const Length2) { return false; }
148 
149 protected:
150 
152  explicit Joint(const JointConf& def);
153 
154 private:
155  friend class JointAtty;
156 
158  using FlagsType = std::uint8_t;
159 
161  enum Flag: FlagsType
162  {
163  // Used when crawling contact graph when forming islands.
164  e_islandFlag = 0x01u,
165 
166  e_collideConnectedFlag = 0x02u
167  };
168 
170  static FlagsType GetFlags(const JointConf& def) noexcept;
171 
173  template <class OUT_TYPE, class IN_TYPE>
174  static OUT_TYPE* Create(IN_TYPE def)
175  {
176  if (OUT_TYPE::IsOkay(def))
177  {
178  return new OUT_TYPE(def);
179  }
180  throw InvalidArgument("definition not okay");
181  }
182 
185  static Joint* Create(const JointConf& def);
186 
189  static void Destroy(const Joint* joint) noexcept;
190 
194  virtual void InitVelocityConstraints(BodyConstraintsMap& bodies,
195  const playrho::StepConf& step,
196  const ConstraintSolverConf& conf) = 0;
197 
202  virtual bool SolveVelocityConstraints(BodyConstraintsMap& bodies,
203  const playrho::StepConf& step) = 0;
204 
207  virtual bool SolvePositionConstraints(BodyConstraintsMap& bodies,
208  const ConstraintSolverConf& conf) const = 0;
209 
211  bool IsIslanded() const noexcept;
212 
214  void SetIslanded() noexcept;
215 
217  void UnsetIslanded() noexcept;
218 
219  Body* const m_bodyA;
220  Body* const m_bodyB;
221  void* m_userData;
222  FlagsType m_flags = 0u;
223 };
224 
225 inline Body* Joint::GetBodyA() const noexcept
226 {
227  return m_bodyA;
228 }
229 
230 inline Body* Joint::GetBodyB() const noexcept
231 {
232  return m_bodyB;
233 }
234 
235 inline void* Joint::GetUserData() const noexcept
236 {
237  return m_userData;
238 }
239 
240 inline void Joint::SetUserData(void* data) noexcept
241 {
242  m_userData = data;
243 }
244 
245 inline bool Joint::GetCollideConnected() const noexcept
246 {
247  return (m_flags & e_collideConnectedFlag) != 0u;
248 }
249 
250 inline bool Joint::IsIslanded() const noexcept
251 {
252  return (m_flags & e_islandFlag) != 0u;
253 }
254 
255 inline void Joint::SetIslanded() noexcept
256 {
257  m_flags |= e_islandFlag;
258 }
259 
260 inline void Joint::UnsetIslanded() noexcept
261 {
262  m_flags &= ~e_islandFlag;
263 }
264 
265 // Free functions...
266 
269 bool IsEnabled(const Joint& j) noexcept;
270 
273 void SetAwake(Joint& j) noexcept;
274 
277 JointCounter GetWorldIndex(const Joint* joint);
278 
279 #ifdef PLAYRHO_PROVIDE_VECTOR_AT
280 BodyConstraintPtr& At(std::vector<BodyConstraintPair>& container, const Body* key);
282 #endif
283 
285 BodyConstraintPtr& At(std::unordered_map<const Body*, BodyConstraint*>& container,
286  const Body* key);
287 
289 const char* ToString(Joint::LimitState val) noexcept;
290 
294 template <class T>
295 inline void IncMotorSpeed(T& j, AngularVelocity delta)
296 {
297  j.SetMotorSpeed(j.GetMotorSpeed() + delta);
298 }
299 
300 } // namespace d2
301 } // namespace playrho
302 
303 #endif // PLAYRHO_DYNAMICS_JOINTS_JOINT_HPP