2 * Copyright (c) 2006-2007 Erin Catto http://www.gphysics.com
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.
21 #include "Joints/b2Joint.h"
22 #include "../Collision/Shapes/b2Shape.h"
24 b2Body::b2Body(const b2BodyDef* bd, b2World* world)
26 b2Assert(world->m_lock == false);
32 m_flags |= e_bulletFlag;
34 if (bd->fixedRotation)
36 m_flags |= e_fixedRotationFlag;
40 m_flags |= e_allowSleepFlag;
44 m_flags |= e_sleepFlag;
49 m_xf.position = bd->position;
50 m_xf.R.Set(bd->angle);
52 m_sweep.localCenter = bd->massData.center;
54 m_sweep.a0 = m_sweep.a = bd->angle;
55 m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
62 m_linearDamping = bd->linearDamping;
63 m_angularDamping = bd->angularDamping;
65 m_force.Set(0.0f, 0.0f);
68 m_linearVelocity.SetZero();
69 m_angularVelocity = 0.0f;
77 m_mass = bd->massData.mass;
81 m_invMass = 1.0f / m_mass;
84 if ((m_flags & b2Body::e_fixedRotationFlag) == 0)
94 if (m_invMass == 0.0f && m_invI == 0.0f)
96 m_type = e_staticType;
100 m_type = e_dynamicType;
103 m_userData = bd->userData;
111 b2Assert(m_world->m_lock == false);
112 // shapes and joints are destroyed in b2World::Destroy
115 b2Shape* b2Body::CreateShape(b2ShapeDef* def)
117 b2Assert(m_world->m_lock == false);
118 if (m_world->m_lock == true)
123 b2Shape* s = b2Shape::Create(def, &m_world->m_blockAllocator);
125 s->m_next = m_shapeList;
131 // Add the shape to the world's broad-phase.
132 s->CreateProxy(m_world->m_broadPhase, m_xf);
134 // Compute the sweep radius for CCD.
135 s->UpdateSweepRadius(m_sweep.localCenter);
140 void b2Body::DestroyShape(b2Shape* s)
142 b2Assert(m_world->m_lock == false);
143 if (m_world->m_lock == true)
148 b2Assert(s->GetBody() == this);
149 s->DestroyProxy(m_world->m_broadPhase);
151 b2Assert(m_shapeCount > 0);
152 b2Shape** node = &m_shapeList;
154 while (*node != NULL)
163 node = &(*node)->m_next;
166 // You tried to remove a shape that is not attached to this body.
174 b2Shape::Destroy(s, &m_world->m_blockAllocator);
177 // TODO_ERIN adjust linear velocity and torque to account for movement of center.
178 void b2Body::SetMass(const b2MassData* massData)
180 b2Assert(m_world->m_lock == false);
181 if (m_world->m_lock == true)
190 m_mass = massData->mass;
194 m_invMass = 1.0f / m_mass;
197 if ((m_flags & b2Body::e_fixedRotationFlag) == 0)
207 // Move center of mass.
208 m_sweep.localCenter = massData->center;
209 m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
211 // Update the sweep radii of all child shapes.
212 for (b2Shape* s = m_shapeList; s; s = s->m_next)
214 s->UpdateSweepRadius(m_sweep.localCenter);
217 int16 oldType = m_type;
218 if (m_invMass == 0.0f && m_invI == 0.0f)
220 m_type = e_staticType;
224 m_type = e_dynamicType;
227 // If the body type changed, we need to refilter the broad-phase proxies.
228 if (oldType != m_type)
230 for (b2Shape* s = m_shapeList; s; s = s->m_next)
232 s->RefilterProxy(m_world->m_broadPhase, m_xf);
237 // TODO_ERIN adjust linear velocity and torque to account for movement of center.
238 void b2Body::SetMassFromShapes()
240 b2Assert(m_world->m_lock == false);
241 if (m_world->m_lock == true)
246 // Compute mass data from shapes. Each shape has its own density.
252 b2Vec2 center = b2Vec2_zero;
253 for (b2Shape* s = m_shapeList; s; s = s->m_next)
256 s->ComputeMass(&massData);
257 m_mass += massData.mass;
258 center += massData.mass * massData.center;
262 // Compute center of mass, and shift the origin to the COM.
265 m_invMass = 1.0f / m_mass;
269 if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0)
271 // Center the inertia about the center of mass.
272 m_I -= m_mass * b2Dot(center, center);
273 b2Assert(m_I > 0.0f);
282 // Move center of mass.
283 m_sweep.localCenter = center;
284 m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
286 // Update the sweep radii of all child shapes.
287 for (b2Shape* s = m_shapeList; s; s = s->m_next)
289 s->UpdateSweepRadius(m_sweep.localCenter);
292 int16 oldType = m_type;
293 if (m_invMass == 0.0f && m_invI == 0.0f)
295 m_type = e_staticType;
299 m_type = e_dynamicType;
302 // If the body type changed, we need to refilter the broad-phase proxies.
303 if (oldType != m_type)
305 for (b2Shape* s = m_shapeList; s; s = s->m_next)
307 s->RefilterProxy(m_world->m_broadPhase, m_xf);
312 bool b2Body::SetXForm(const b2Vec2& position, float32 angle)
314 b2Assert(m_world->m_lock == false);
315 if (m_world->m_lock == true)
326 m_xf.position = position;
328 m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter);
329 m_sweep.a0 = m_sweep.a = angle;
332 for (b2Shape* s = m_shapeList; s; s = s->m_next)
334 bool inRange = s->Synchronize(m_world->m_broadPhase, m_xf, m_xf);
336 if (inRange == false)
345 m_flags |= e_frozenFlag;
346 m_linearVelocity.SetZero();
347 m_angularVelocity = 0.0f;
348 for (b2Shape* s = m_shapeList; s; s = s->m_next)
350 s->DestroyProxy(m_world->m_broadPhase);
358 m_world->m_broadPhase->Commit();
362 bool b2Body::SynchronizeShapes()
365 xf1.R.Set(m_sweep.a0);
366 xf1.position = m_sweep.c0 - b2Mul(xf1.R, m_sweep.localCenter);
369 for (b2Shape* s = m_shapeList; s; s = s->m_next)
371 inRange = s->Synchronize(m_world->m_broadPhase, xf1, m_xf);
372 if (inRange == false)
378 if (inRange == false)
380 m_flags |= e_frozenFlag;
381 m_linearVelocity.SetZero();
382 m_angularVelocity = 0.0f;
383 for (b2Shape* s = m_shapeList; s; s = s->m_next)
385 s->DestroyProxy(m_world->m_broadPhase);