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_BODY_H
20 #define B2_BODY_H
21 
22 #include "../Common/b2Math.h"
23 #include "../Collision/Shapes/b2Shape.h"
24 #include "Joints/b2Joint.h"
25 
26 #include <memory>
27 
28 class b2Joint;
29 class b2Contact;
30 class b2World;
31 struct b2JointEdge;
32 struct b2ContactEdge;
33 
34 /// A body definition holds all the data needed to construct a rigid body.
35 /// You can safely re-use body definitions.
36 struct b2BodyDef
37 {
38 	/// This constructor sets the body definition default values.
b2BodyDefb2BodyDef39 	b2BodyDef()
40 	{
41 		massData.center.SetZero();
42 		massData.mass = 0.0f;
43 		massData.I = 0.0f;
44 		userData = NULL;
45 		position.Set(0.0f, 0.0f);
46 		angle = 0.0f;
47 		linearDamping = 0.0f;
48 		angularDamping = 0.0f;
49 		allowSleep = true;
50 		isSleeping = false;
51 		fixedRotation = false;
52 		isBullet = false;
53 	}
54 
55 	/// You can use this to initialized the mass properties of the body.
56 	/// If you prefer, you can set the mass properties after the shapes
57 	/// have been added using b2Body::SetMassFromShapes.
58 	b2MassData massData;
59 
60 	/// Use this to store application specific body data.
61 	void* userData;
62 
63 	/// The world position of the body. Avoid creating bodies at the origin
64 	/// since this can lead to many overlapping shapes.
65 	b2Vec2 position;
66 
67 	/// The world angle of the body in radians.
68 	float32 angle;
69 
70 	/// Linear damping is use to reduce the linear velocity. The damping parameter
71 	/// can be larger than 1.0f but the damping effect becomes sensitive to the
72 	/// time step when the damping parameter is large.
73 	float32 linearDamping;
74 
75 	/// Angular damping is use to reduce the angular velocity. The damping parameter
76 	/// can be larger than 1.0f but the damping effect becomes sensitive to the
77 	/// time step when the damping parameter is large.
78 	float32 angularDamping;
79 
80 	/// Set this flag to false if this body should never fall asleep. Note that
81 	/// this increases CPU usage.
82 	bool allowSleep;
83 
84 	/// Is this body initially sleeping?
85 	bool isSleeping;
86 
87 	/// Should this body be prevented from rotating? Useful for characters.
88 	bool fixedRotation;
89 
90 	/// Is this a fast moving body that should be prevented from tunneling through
91 	/// other moving bodies? Note that all bodies are prevented from tunneling through
92 	/// static bodies.
93 	/// @warning You should use this flag sparingly since it increases processing time.
94 	bool isBullet;
95 };
96 
97 /// A rigid body.
98 class b2Body
99 {
100 public:
101 	/// Creates a shape and attach it to this body.
102 	/// @param shapeDef the shape definition.
103 	/// @warning This function is locked during callbacks.
104 	b2Shape* CreateShape(b2ShapeDef* shapeDef);
105 
106 	/// Destroy a shape. This removes the shape from the broad-phase and
107 	/// therefore destroys any contacts associated with this shape. All shapes
108 	/// attached to a body are implicitly destroyed when the body is destroyed.
109 	/// @param shape the shape to be removed.
110 	/// @warning This function is locked during callbacks.
111 	void DestroyShape(b2Shape* shape);
112 
113 	/// Set the mass properties. Note that this changes the center of mass position.
114 	/// If you are not sure how to compute mass properties, use SetMassFromShapes.
115 	/// The inertia tensor is assumed to be relative to the center of mass.
116 	/// @param massData the mass properties.
117 	void SetMass(const b2MassData* massData);
118 
119 	/// Compute the mass properties from the attached shapes. You typically call this
120 	/// after adding all the shapes. If you add or remove shapes later, you may want
121 	/// to call this again. Note that this changes the center of mass position.
122 	void SetMassFromShapes();
123 
124 	/// Set the position of the body's origin and rotation (radians).
125 	/// This breaks any contacts and wakes the other bodies.
126 	/// @param position the new world position of the body's origin (not necessarily
127 	/// the center of mass).
128 	/// @param angle the new world rotation angle of the body in radians.
129 	/// @return false if the movement put a shape outside the world. In this case the
130 	/// body is automatically frozen.
131 	bool SetXForm(const b2Vec2& position, float32 angle);
132 
133 	/// Get the body transform for the body's origin.
134 	/// @return the world transform of the body's origin.
135 	const b2XForm& GetXForm() const;
136 
137 	/// Get the world body origin position.
138 	/// @return the world position of the body's origin.
139 	const b2Vec2& GetPosition() const;
140 
141 	/// Get the angle in radians.
142 	/// @return the current world rotation angle in radians.
143 	float32 GetAngle() const;
144 
145 	/// Get the world position of the center of mass.
146 	const b2Vec2& GetWorldCenter() const;
147 
148 	/// Get the local position of the center of mass.
149 	const b2Vec2& GetLocalCenter() const;
150 
151 	/// Set the linear velocity of the center of mass.
152 	/// @param v the new linear velocity of the center of mass.
153 	void SetLinearVelocity(const b2Vec2& v);
154 
155 	/// Get the linear velocity of the center of mass.
156 	/// @return the linear velocity of the center of mass.
157 	b2Vec2 GetLinearVelocity() const;
158 
159 	/// Set the angular velocity.
160 	/// @param omega the new angular velocity in radians/second.
161 	void SetAngularVelocity(float32 omega);
162 
163 	/// Get the angular velocity.
164 	/// @return the angular velocity in radians/second.
165 	float32 GetAngularVelocity() const;
166 
167 	/// Apply a force at a world point. If the force is not
168 	/// applied at the center of mass, it will generate a torque and
169 	/// affect the angular velocity. This wakes up the body.
170 	/// @param force the world force vector, usually in Newtons (N).
171 	/// @param point the world position of the point of application.
172 	void ApplyForce(const b2Vec2& force, const b2Vec2& point);
173 
174 	/// Apply a torque. This affects the angular velocity
175 	/// without affecting the linear velocity of the center of mass.
176 	/// This wakes up the body.
177 	/// @param torque about the z-axis (out of the screen), usually in N-m.
178 	void ApplyTorque(float32 torque);
179 
180 	/// Apply an impulse at a point. This immediately modifies the velocity.
181 	/// It also modifies the angular velocity if the point of application
182 	/// is not at the center of mass. This wakes up the body.
183 	/// @param impulse the world impulse vector, usually in N-seconds or kg-m/s.
184 	/// @param point the world position of the point of application.
185 	void ApplyImpulse(const b2Vec2& impulse, const b2Vec2& point);
186 
187 	/// Get the total mass of the body.
188 	/// @return the mass, usually in kilograms (kg).
189 	float32 GetMass() const;
190 
191 	/// Get the central rotational inertia of the body.
192 	/// @return the rotational inertia, usually in kg-m^2.
193 	float32 GetInertia() const;
194 
195 	/// Get the world coordinates of a point given the local coordinates.
196 	/// @param localPoint a point on the body measured relative the the body's origin.
197 	/// @return the same point expressed in world coordinates.
198 	b2Vec2 GetWorldPoint(const b2Vec2& localPoint) const;
199 
200 	/// Get the world coordinates of a vector given the local coordinates.
201 	/// @param localVector a vector fixed in the body.
202 	/// @return the same vector expressed in world coordinates.
203 	b2Vec2 GetWorldVector(const b2Vec2& localVector) const;
204 
205 	/// Gets a local point relative to the body's origin given a world point.
206 	/// @param a point in world coordinates.
207 	/// @return the corresponding local point relative to the body's origin.
208 	b2Vec2 GetLocalPoint(const b2Vec2& worldPoint) const;
209 
210 	/// Gets a local vector given a world vector.
211 	/// @param a vector in world coordinates.
212 	/// @return the corresponding local vector.
213 	b2Vec2 GetLocalVector(const b2Vec2& worldVector) const;
214 
215 	/// Get the world linear velocity of a world point attached to this body.
216 	/// @param a point in world coordinates.
217 	/// @return the world velocity of a point.
218 	b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const;
219 
220 	/// Get the world velocity of a local point.
221 	/// @param a point in local coordinates.
222 	/// @return the world velocity of a point.
223 	b2Vec2 GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const;
224 
225 	/// Is this body treated like a bullet for continuous collision detection?
226 	bool IsBullet() const;
227 
228 	/// Should this body be treated like a bullet for continuous collision detection?
229 	void SetBullet(bool flag);
230 
231 	/// Is this body static (immovable)?
232 	bool IsStatic() const;
233 
234 	/// Is this body dynamic (movable)?
235 	bool IsDynamic() const;
236 
237 	/// Is this body frozen?
238 	bool IsFrozen() const;
239 
240 	/// Is this body sleeping (not simulating).
241 	bool IsSleeping() const;
242 
243 	/// You can disable sleeping on this body.
244 	void AllowSleeping(bool flag);
245 
246 	/// Wake up this body so it will begin simulating.
247 	void WakeUp();
248 
249 	/// Put this body to sleep so it will stop simulating.
250 	/// This also sets the velocity to zero.
251 	void PutToSleep();
252 
253 	/// Get the list of all shapes attached to this body.
254 	b2Shape* GetShapeList();
255 
256 	/// Get the list of all joints attached to this body.
257 	b2JointEdge* GetJointList();
258 
259 	/// Get the next body in the world's body list.
260 	b2Body* GetNext();
261 
262 	/// Get the user data pointer that was provided in the body definition.
263 	void* GetUserData();
264 
265 	/// Set the user data. Use this to store your application specific data.
266 	void SetUserData(void* data);
267 
268 	/// Get the parent world of this body.
269 	b2World* GetWorld();
270 
271 public:
272 
273 	friend class b2World;
274 	friend class b2Island;
275 	friend class b2ContactManager;
276 	friend class b2ContactSolver;
277 
278 	friend class b2DistanceJoint;
279 	friend class b2GearJoint;
280 	friend class b2MouseJoint;
281 	friend class b2PrismaticJoint;
282 	friend class b2PulleyJoint;
283 	friend class b2RevoluteJoint;
284 
285 	// m_flags
286 	enum
287 	{
288 		e_frozenFlag		= 0x0002,
289 		e_islandFlag		= 0x0004,
290 		e_sleepFlag			= 0x0008,
291 		e_allowSleepFlag	= 0x0010,
292 		e_bulletFlag		= 0x0020,
293 		e_fixedRotationFlag	= 0x0040,
294 	};
295 
296 	// m_type
297 	enum
298 	{
299 		e_staticType,
300 		e_dynamicType,
301 		e_maxTypes,
302 	};
303 
304 	b2Body(const b2BodyDef* bd, b2World* world);
305 	~b2Body();
306 
307 	bool SynchronizeShapes();
308 
309 	void SynchronizeTransform();
310 
311 	// This is used to prevent connected bodies from colliding.
312 	// It may lie, depending on the collideConnected flag.
313 	bool IsConnected(const b2Body* other) const;
314 
315 	void Advance(float32 t);
316 
317 	uint16 m_flags;
318 	int16 m_type;
319 
320 	b2XForm m_xf;		// the body origin transform
321 
322 	b2Sweep m_sweep;	// the swept motion for CCD
323 
324 	b2Vec2 m_linearVelocity;
325 	float32 m_angularVelocity;
326 
327 	b2Vec2 m_force;
328 	float32 m_torque;
329 
330 	b2World* m_world;
331 	b2Body* m_prev;
332 	b2Body* m_next;
333 
334 	b2Shape* m_shapeList;
335 	int32 m_shapeCount;
336 
337 	b2JointEdge* m_jointList;
338 	b2ContactEdge* m_contactList;
339 
340 	float32 m_mass, m_invMass;
341 	float32 m_I, m_invI;
342 
343 	float32 m_linearDamping;
344 	float32 m_angularDamping;
345 
346 	float32 m_sleepTime;
347 
348 	void* m_userData;
349 };
350 
GetXForm()351 inline const b2XForm& b2Body::GetXForm() const
352 {
353 	return m_xf;
354 }
355 
GetPosition()356 inline const b2Vec2& b2Body::GetPosition() const
357 {
358 	return m_xf.position;
359 }
360 
GetAngle()361 inline float32 b2Body::GetAngle() const
362 {
363 	return m_sweep.a;
364 }
365 
GetWorldCenter()366 inline const b2Vec2& b2Body::GetWorldCenter() const
367 {
368 	return m_sweep.c;
369 }
370 
GetLocalCenter()371 inline const b2Vec2& b2Body::GetLocalCenter() const
372 {
373 	return m_sweep.localCenter;
374 }
375 
SetLinearVelocity(const b2Vec2 & v)376 inline void b2Body::SetLinearVelocity(const b2Vec2& v)
377 {
378 	m_linearVelocity = v;
379 }
380 
GetLinearVelocity()381 inline b2Vec2 b2Body::GetLinearVelocity() const
382 {
383 	return m_linearVelocity;
384 }
385 
SetAngularVelocity(float32 w)386 inline void b2Body::SetAngularVelocity(float32 w)
387 {
388 	m_angularVelocity = w;
389 }
390 
GetAngularVelocity()391 inline float32 b2Body::GetAngularVelocity() const
392 {
393 	return m_angularVelocity;
394 }
395 
GetMass()396 inline float32 b2Body::GetMass() const
397 {
398 	return m_mass;
399 }
400 
GetInertia()401 inline float32 b2Body::GetInertia() const
402 {
403 	return m_I;
404 }
405 
GetWorldPoint(const b2Vec2 & localPoint)406 inline b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint) const
407 {
408 	return b2Mul(m_xf, localPoint);
409 }
410 
GetWorldVector(const b2Vec2 & localVector)411 inline b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector) const
412 {
413 	return b2Mul(m_xf.R, localVector);
414 }
415 
GetLocalPoint(const b2Vec2 & worldPoint)416 inline b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint) const
417 {
418 	return b2MulT(m_xf, worldPoint);
419 }
420 
GetLocalVector(const b2Vec2 & worldVector)421 inline b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector) const
422 {
423 	return b2MulT(m_xf.R, worldVector);
424 }
425 
GetLinearVelocityFromWorldPoint(const b2Vec2 & worldPoint)426 inline b2Vec2 b2Body::GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const
427 {
428 	return m_linearVelocity + b2Cross(m_angularVelocity, worldPoint - m_sweep.c);
429 }
430 
GetLinearVelocityFromLocalPoint(const b2Vec2 & localPoint)431 inline b2Vec2 b2Body::GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const
432 {
433 	return GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint));
434 }
435 
IsBullet()436 inline bool b2Body::IsBullet() const
437 {
438 	return (m_flags & e_bulletFlag) == e_bulletFlag;
439 }
440 
SetBullet(bool flag)441 inline void b2Body::SetBullet(bool flag)
442 {
443 	if (flag)
444 	{
445 		m_flags |= e_bulletFlag;
446 	}
447 	else
448 	{
449 		m_flags &= ~e_bulletFlag;
450 	}
451 }
452 
IsStatic()453 inline bool b2Body::IsStatic() const
454 {
455 	return m_type == e_staticType;
456 }
457 
IsDynamic()458 inline bool b2Body::IsDynamic() const
459 {
460 	return m_type == e_dynamicType;
461 }
462 
IsFrozen()463 inline bool b2Body::IsFrozen() const
464 {
465 	return (m_flags & e_frozenFlag) == e_frozenFlag;
466 }
467 
IsSleeping()468 inline bool b2Body::IsSleeping() const
469 {
470 	return (m_flags & e_sleepFlag) == e_sleepFlag;
471 }
472 
AllowSleeping(bool flag)473 inline void b2Body::AllowSleeping(bool flag)
474 {
475 	if (flag)
476 	{
477 		m_flags |= e_allowSleepFlag;
478 	}
479 	else
480 	{
481 		m_flags &= ~e_allowSleepFlag;
482 		WakeUp();
483 	}
484 }
485 
WakeUp()486 inline void b2Body::WakeUp()
487 {
488 	m_flags &= ~e_sleepFlag;
489 	m_sleepTime = 0.0f;
490 }
491 
PutToSleep()492 inline void b2Body::PutToSleep()
493 {
494 	m_flags |= e_sleepFlag;
495 	m_sleepTime = 0.0f;
496 	m_linearVelocity.SetZero();
497 	m_angularVelocity = 0.0f;
498 	m_force.SetZero();
499 	m_torque = 0.0f;
500 }
501 
GetShapeList()502 inline b2Shape* b2Body::GetShapeList()
503 {
504 	return m_shapeList;
505 }
506 
GetJointList()507 inline b2JointEdge* b2Body::GetJointList()
508 {
509 	return m_jointList;
510 }
511 
GetNext()512 inline b2Body* b2Body::GetNext()
513 {
514 	return m_next;
515 }
516 
GetUserData()517 inline void* b2Body::GetUserData()
518 {
519 	return m_userData;
520 }
521 
SetUserData(void * data)522 inline void b2Body::SetUserData(void* data)
523 {
524 	m_userData = data;
525 }
526 
IsConnected(const b2Body * other)527 inline bool b2Body::IsConnected(const b2Body* other) const
528 {
529 	for (b2JointEdge* jn = m_jointList; jn; jn = jn->next)
530 	{
531 		if (jn->other == other)
532 			return jn->joint->m_collideConnected == false;
533 	}
534 
535 	return false;
536 }
537 
ApplyForce(const b2Vec2 & force,const b2Vec2 & point)538 inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point)
539 {
540 	if (IsSleeping())
541 	{
542 		WakeUp();
543 	}
544 	m_force += force;
545 	m_torque += b2Cross(point - m_sweep.c, force);
546 }
547 
ApplyTorque(float32 torque)548 inline void b2Body::ApplyTorque(float32 torque)
549 {
550 	if (IsSleeping())
551 	{
552 		WakeUp();
553 	}
554 	m_torque += torque;
555 }
556 
ApplyImpulse(const b2Vec2 & impulse,const b2Vec2 & point)557 inline void b2Body::ApplyImpulse(const b2Vec2& impulse, const b2Vec2& point)
558 {
559 	if (IsSleeping())
560 	{
561 		WakeUp();
562 	}
563 	m_linearVelocity += m_invMass * impulse;
564 	m_angularVelocity += m_invI * b2Cross(point - m_sweep.c, impulse);
565 }
566 
SynchronizeTransform()567 inline void b2Body::SynchronizeTransform()
568 {
569 	m_xf.R.Set(m_sweep.a);
570 	m_xf.position = m_sweep.c - b2Mul(m_xf.R, m_sweep.localCenter);
571 }
572 
Advance(float32 t)573 inline void b2Body::Advance(float32 t)
574 {
575 	// Advance to the new safe time.
576 	m_sweep.Advance(t);
577 	m_sweep.c = m_sweep.c0;
578 	m_sweep.a = m_sweep.a0;
579 	SynchronizeTransform();
580 }
581 
GetWorld()582 inline b2World* b2Body::GetWorld()
583 {
584 	return m_world;
585 }
586 
587 #endif
588