1 /*
2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
3 *
4 * This software is provided 'as-is', without any express or implied
5 * warranty.  In no event will the authors be held liable for any damages
6 * arising from the use of this software.
7 * Permission is granted to anyone to use this software for any purpose,
8 * including commercial applications, and to alter it and redistribute it
9 * freely, subject to the following restrictions:
10 * 1. The origin of this software must not be misrepresented; you must not
11 * claim that you wrote the original software. If you use this software
12 * in a product, an acknowledgment in the product documentation would be
13 * appreciated but is not required.
14 * 2. Altered source versions must be plainly marked as such, and must not be
15 * misrepresented as being the original software.
16 * 3. This notice may not be removed or altered from any source distribution.
17 */
18 
19 #ifndef B2_JOINT_H
20 #define B2_JOINT_H
21 
22 #include <Box2D/Common/b2Math.h>
23 
24 class b2Body;
25 class b2Joint;
26 struct b2TimeStep;
27 class b2BlockAllocator;
28 
29 enum b2JointType
30 {
31 	e_unknownJoint,
32 	e_revoluteJoint,
33 	e_prismaticJoint,
34 	e_distanceJoint,
35 	e_pulleyJoint,
36 	e_mouseJoint,
37 	e_gearJoint,
38 	e_lineJoint,
39     e_weldJoint,
40 	e_frictionJoint,
41 	e_ropeJoint
42 };
43 
44 enum b2LimitState
45 {
46 	e_inactiveLimit,
47 	e_atLowerLimit,
48 	e_atUpperLimit,
49 	e_equalLimits
50 };
51 
52 struct b2Jacobian
53 {
54 	b2Vec2 linearA;
55 	qreal angularA;
56 	b2Vec2 linearB;
57 	qreal angularB;
58 
59 	void SetZero();
60 	void Set(const b2Vec2& x1, qreal a1, const b2Vec2& x2, qreal a2);
61 	qreal Compute(const b2Vec2& x1, qreal a1, const b2Vec2& x2, qreal a2);
62 };
63 
64 /// A joint edge is used to connect bodies and joints together
65 /// in a joint graph where each body is a node and each joint
66 /// is an edge. A joint edge belongs to a doubly linked list
67 /// maintained in each attached body. Each joint has two joint
68 /// nodes, one for each attached body.
69 struct b2JointEdge
70 {
71 	b2Body* other;			///< provides quick access to the other body attached.
72 	b2Joint* joint;			///< the joint
73 	b2JointEdge* prev;		///< the previous joint edge in the body's joint list
74 	b2JointEdge* next;		///< the next joint edge in the body's joint list
75 };
76 
77 /// Joint definitions are used to construct joints.
78 struct b2JointDef
79 {
b2JointDefb2JointDef80 	b2JointDef()
81 	{
82 		type = e_unknownJoint;
83 		userData = NULL;
84 		bodyA = NULL;
85 		bodyB = NULL;
86 		collideConnected = false;
87 	}
88 
89 	/// The joint type is set automatically for concrete joint types.
90 	b2JointType type;
91 
92 	/// Use this to attach application specific data to your joints.
93 	void* userData;
94 
95 	/// The first attached body.
96 	b2Body* bodyA;
97 
98 	/// The second attached body.
99 	b2Body* bodyB;
100 
101 	/// Set this flag to true if the attached bodies should collide.
102 	bool collideConnected;
103 };
104 
105 /// The base joint class. Joints are used to constraint two bodies together in
106 /// various fashions. Some joints also feature limits and motors.
107 class b2Joint
108 {
109 public:
110 
111 	/// Get the type of the concrete joint.
112 	b2JointType GetType() const;
113 
114 	/// Get the first body attached to this joint.
115 	b2Body* GetBodyA();
116 
117 	/// Get the second body attached to this joint.
118 	b2Body* GetBodyB();
119 
120 	/// Get the anchor point on bodyA in world coordinates.
121 	virtual b2Vec2 GetAnchorA() const = 0;
122 
123 	/// Get the anchor point on bodyB in world coordinates.
124 	virtual b2Vec2 GetAnchorB() const = 0;
125 
126 	/// Get the reaction force on body2 at the joint anchor in Newtons.
127 	virtual b2Vec2 GetReactionForce(qreal inv_dt) const = 0;
128 
129 	/// Get the reaction torque on body2 in N*m.
130 	virtual qreal GetReactionTorque(qreal inv_dt) const = 0;
131 
132 	/// Get the next joint the world joint list.
133 	b2Joint* GetNext();
134 	const b2Joint* GetNext() const;
135 
136 	/// Get the user data pointer.
137 	void* GetUserData() const;
138 
139 	/// Set the user data pointer.
140 	void SetUserData(void* data);
141 
142 	/// Short-cut function to determine if either body is inactive.
143 	bool IsActive() const;
144 
145 protected:
146 	friend class b2World;
147 	friend class b2Body;
148 	friend class b2Island;
149 
150 	static b2Joint* Create(const b2JointDef* def, b2BlockAllocator* allocator);
151 	static void Destroy(b2Joint* joint, b2BlockAllocator* allocator);
152 
153 	b2Joint(const b2JointDef* def);
~b2Joint()154 	virtual ~b2Joint() {}
155 
156 	virtual void InitVelocityConstraints(const b2TimeStep& step) = 0;
157 	virtual void SolveVelocityConstraints(const b2TimeStep& step) = 0;
158 
159 	// This returns true if the position errors are within tolerance.
160 	virtual bool SolvePositionConstraints(qreal baumgarte) = 0;
161 
162 	b2JointType m_type;
163 	b2Joint* m_prev;
164 	b2Joint* m_next;
165 	b2JointEdge m_edgeA;
166 	b2JointEdge m_edgeB;
167 	b2Body* m_bodyA;
168 	b2Body* m_bodyB;
169 
170 	bool m_islandFlag;
171 	bool m_collideConnected;
172 
173 	void* m_userData;
174 
175 	// Cache here per time step to reduce cache misses.
176 	// TODO_ERIN will be wrong if the mass changes.
177 	b2Vec2 m_localCenterA, m_localCenterB;
178 	qreal m_invMassA, m_invIA;
179 	qreal m_invMassB, m_invIB;
180 };
181 
SetZero()182 inline void b2Jacobian::SetZero()
183 {
184 	linearA.SetZero(); angularA = 0.0f;
185 	linearB.SetZero(); angularB = 0.0f;
186 }
187 
Set(const b2Vec2 & x1,qreal a1,const b2Vec2 & x2,qreal a2)188 inline void b2Jacobian::Set(const b2Vec2& x1, qreal a1, const b2Vec2& x2, qreal a2)
189 {
190 	linearA = x1; angularA = a1;
191 	linearB = x2; angularB = a2;
192 }
193 
Compute(const b2Vec2 & x1,qreal a1,const b2Vec2 & x2,qreal a2)194 inline qreal b2Jacobian::Compute(const b2Vec2& x1, qreal a1, const b2Vec2& x2, qreal a2)
195 {
196 	return b2Dot(linearA, x1) + angularA * a1 + b2Dot(linearB, x2) + angularB * a2;
197 }
198 
GetType()199 inline b2JointType b2Joint::GetType() const
200 {
201 	return m_type;
202 }
203 
GetBodyA()204 inline b2Body* b2Joint::GetBodyA()
205 {
206 	return m_bodyA;
207 }
208 
GetBodyB()209 inline b2Body* b2Joint::GetBodyB()
210 {
211 	return m_bodyB;
212 }
213 
GetNext()214 inline b2Joint* b2Joint::GetNext()
215 {
216 	return m_next;
217 }
218 
GetNext()219 inline const b2Joint* b2Joint::GetNext() const
220 {
221 	return m_next;
222 }
223 
GetUserData()224 inline void* b2Joint::GetUserData() const
225 {
226 	return m_userData;
227 }
228 
SetUserData(void * data)229 inline void b2Joint::SetUserData(void* data)
230 {
231 	m_userData = data;
232 }
233 
234 #endif
235