2
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
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.
23
void DestructionListener::SayGoodbye(b2Joint* joint)
25
if (test->m_mouseJoint == joint)
27
test->m_mouseJoint = NULL;
31
test->JointDestroyed(joint);
38
gravity.Set(0.0f, -10.0f);
39
m_world = new b2World(gravity);
45
m_destructionListener.test = this;
46
m_world->SetDestructionListener(&m_destructionListener);
47
m_world->SetContactListener(this);
48
m_world->SetDebugDraw(&m_debugDraw);
50
m_bombSpawning = false;
55
m_groundBody = m_world->CreateBody(&bodyDef);
57
memset(&m_maxProfile, 0, sizeof(b2Profile));
58
memset(&m_totalProfile, 0, sizeof(b2Profile));
63
// By deleting the world, we delete the bomb, mouse joint, etc.
68
void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
70
const b2Manifold* manifold = contact->GetManifold();
72
if (manifold->pointCount == 0)
77
b2Fixture* fixtureA = contact->GetFixtureA();
78
b2Fixture* fixtureB = contact->GetFixtureB();
80
b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
81
b2GetPointStates(state1, state2, oldManifold, manifold);
83
b2WorldManifold worldManifold;
84
contact->GetWorldManifold(&worldManifold);
86
for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
88
ContactPoint* cp = m_points + m_pointCount;
89
cp->fixtureA = fixtureA;
90
cp->fixtureB = fixtureB;
91
cp->position = worldManifold.points[i];
92
cp->normal = worldManifold.normal;
93
cp->state = state2[i];
98
void Test::DrawTitle(int x, int y, const char *string)
100
m_debugDraw.DrawString(x, y, string);
103
class QueryCallback : public b2QueryCallback
106
QueryCallback(const b2Vec2& point)
112
bool ReportFixture(b2Fixture* fixture)
114
b2Body* body = fixture->GetBody();
115
if (body->GetType() == b2_dynamicBody)
117
bool inside = fixture->TestPoint(m_point);
122
// We are done, terminate the query.
127
// Continue the query.
132
b2Fixture* m_fixture;
135
void Test::MouseDown(const b2Vec2& p)
139
if (m_mouseJoint != NULL)
147
d.Set(0.001f, 0.001f);
148
aabb.lowerBound = p - d;
149
aabb.upperBound = p + d;
151
// Query the world for overlapping shapes.
152
QueryCallback callback(p);
153
m_world->QueryAABB(&callback, aabb);
155
if (callback.m_fixture)
157
b2Body* body = callback.m_fixture->GetBody();
159
md.bodyA = m_groundBody;
162
md.maxForce = 1000.0f * body->GetMass();
163
m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
164
body->SetAwake(true);
168
void Test::SpawnBomb(const b2Vec2& worldPt)
170
m_bombSpawnPoint = worldPt;
171
m_bombSpawning = true;
174
void Test::CompleteBombSpawn(const b2Vec2& p)
176
if (m_bombSpawning == false)
181
const float multiplier = 30.0f;
182
b2Vec2 vel = m_bombSpawnPoint - p;
184
LaunchBomb(m_bombSpawnPoint,vel);
185
m_bombSpawning = false;
188
void Test::ShiftMouseDown(const b2Vec2& p)
192
if (m_mouseJoint != NULL)
200
void Test::MouseUp(const b2Vec2& p)
204
m_world->DestroyJoint(m_mouseJoint);
210
CompleteBombSpawn(p);
214
void Test::MouseMove(const b2Vec2& p)
220
m_mouseJoint->SetTarget(p);
224
void Test::LaunchBomb()
226
b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
227
b2Vec2 v = -5.0f * p;
231
void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
235
m_world->DestroyBody(m_bomb);
240
bd.type = b2_dynamicBody;
241
bd.position = position;
243
m_bomb = m_world->CreateBody(&bd);
244
m_bomb->SetLinearVelocity(velocity);
246
b2CircleShape circle;
247
circle.m_radius = 0.3f;
252
fd.restitution = 0.0f;
254
b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
255
b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);
258
aabb.lowerBound = minV;
259
aabb.upperBound = maxV;
261
m_bomb->CreateFixture(&fd);
264
void Test::Step(Settings* settings)
266
float32 timeStep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);
270
if (settings->singleStep)
272
settings->singleStep = 0;
279
m_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
284
flags += settings->drawShapes * b2Draw::e_shapeBit;
285
flags += settings->drawJoints * b2Draw::e_jointBit;
286
flags += settings->drawAABBs * b2Draw::e_aabbBit;
287
flags += settings->drawPairs * b2Draw::e_pairBit;
288
flags += settings->drawCOMs * b2Draw::e_centerOfMassBit;
289
m_debugDraw.SetFlags(flags);
291
m_world->SetWarmStarting(settings->enableWarmStarting > 0);
292
m_world->SetContinuousPhysics(settings->enableContinuous > 0);
293
m_world->SetSubStepping(settings->enableSubStepping > 0);
297
m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);
299
m_world->DrawDebugData();
306
if (settings->drawStats)
308
int32 bodyCount = m_world->GetBodyCount();
309
int32 contactCount = m_world->GetContactCount();
310
int32 jointCount = m_world->GetJointCount();
311
m_debugDraw.DrawString(5, m_textLine, "bodies/contacts/joints = %d/%d/%d", bodyCount, contactCount, jointCount);
314
int32 proxyCount = m_world->GetProxyCount();
315
int32 height = m_world->GetTreeHeight();
316
int32 balance = m_world->GetTreeBalance();
317
float32 quality = m_world->GetTreeQuality();
318
m_debugDraw.DrawString(5, m_textLine, "proxies/height/balance/quality = %d/%d/%d/%g", proxyCount, height, balance, quality);
322
// Track maximum profile times
324
const b2Profile& p = m_world->GetProfile();
325
m_maxProfile.step = b2Max(m_maxProfile.step, p.step);
326
m_maxProfile.collide = b2Max(m_maxProfile.collide, p.collide);
327
m_maxProfile.solve = b2Max(m_maxProfile.solve, p.solve);
328
m_maxProfile.solveInit = b2Max(m_maxProfile.solveInit, p.solveInit);
329
m_maxProfile.solveVelocity = b2Max(m_maxProfile.solveVelocity, p.solveVelocity);
330
m_maxProfile.solvePosition = b2Max(m_maxProfile.solvePosition, p.solvePosition);
331
m_maxProfile.solveTOI = b2Max(m_maxProfile.solveTOI, p.solveTOI);
332
m_maxProfile.broadphase = b2Max(m_maxProfile.broadphase, p.broadphase);
334
m_totalProfile.step += p.step;
335
m_totalProfile.collide += p.collide;
336
m_totalProfile.solve += p.solve;
337
m_totalProfile.solveInit += p.solveInit;
338
m_totalProfile.solveVelocity += p.solveVelocity;
339
m_totalProfile.solvePosition += p.solvePosition;
340
m_totalProfile.solveTOI += p.solveTOI;
341
m_totalProfile.broadphase += p.broadphase;
344
if (settings->drawProfile)
346
const b2Profile& p = m_world->GetProfile();
348
b2Profile aveProfile;
349
memset(&aveProfile, 0, sizeof(b2Profile));
352
float32 scale = 1.0f / m_stepCount;
353
aveProfile.step = scale * m_totalProfile.step;
354
aveProfile.collide = scale * m_totalProfile.collide;
355
aveProfile.solve = scale * m_totalProfile.solve;
356
aveProfile.solveInit = scale * m_totalProfile.solveInit;
357
aveProfile.solveVelocity = scale * m_totalProfile.solveVelocity;
358
aveProfile.solvePosition = scale * m_totalProfile.solvePosition;
359
aveProfile.solveTOI = scale * m_totalProfile.solveTOI;
360
aveProfile.broadphase = scale * m_totalProfile.broadphase;
363
m_debugDraw.DrawString(5, m_textLine, "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, m_maxProfile.step);
365
m_debugDraw.DrawString(5, m_textLine, "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, m_maxProfile.collide);
367
m_debugDraw.DrawString(5, m_textLine, "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, m_maxProfile.solve);
369
m_debugDraw.DrawString(5, m_textLine, "solve init [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveInit, aveProfile.solveInit, m_maxProfile.solveInit);
371
m_debugDraw.DrawString(5, m_textLine, "solve velocity [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveVelocity, aveProfile.solveVelocity, m_maxProfile.solveVelocity);
373
m_debugDraw.DrawString(5, m_textLine, "solve position [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solvePosition, aveProfile.solvePosition, m_maxProfile.solvePosition);
375
m_debugDraw.DrawString(5, m_textLine, "solveTOI [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveTOI, aveProfile.solveTOI, m_maxProfile.solveTOI);
377
m_debugDraw.DrawString(5, m_textLine, "broad-phase [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.broadphase, aveProfile.broadphase, m_maxProfile.broadphase);
383
b2Vec2 p1 = m_mouseJoint->GetAnchorB();
384
b2Vec2 p2 = m_mouseJoint->GetTarget();
387
c.Set(0.0f, 1.0f, 0.0f);
388
m_debugDraw.DrawPoint(p1, 4.0f, c);
389
m_debugDraw.DrawPoint(p2, 4.0f, c);
391
c.Set(0.8f, 0.8f, 0.8f);
392
m_debugDraw.DrawSegment(p1, p2, c);
398
c.Set(0.0f, 0.0f, 1.0f);
399
m_debugDraw.DrawPoint(m_bombSpawnPoint, 4.0f, c);
401
c.Set(0.8f, 0.8f, 0.8f);
402
m_debugDraw.DrawSegment(m_mouseWorld, m_bombSpawnPoint, c);
405
if (settings->drawContactPoints)
407
//const float32 k_impulseScale = 0.1f;
408
const float32 k_axisScale = 0.3f;
410
for (int32 i = 0; i < m_pointCount; ++i)
412
ContactPoint* point = m_points + i;
414
if (point->state == b2_addState)
417
m_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
419
else if (point->state == b2_persistState)
422
m_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
425
if (settings->drawContactNormals == 1)
427
b2Vec2 p1 = point->position;
428
b2Vec2 p2 = p1 + k_axisScale * point->normal;
429
m_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f));
431
else if (settings->drawContactForces == 1)
433
//b2Vec2 p1 = point->position;
434
//b2Vec2 p2 = p1 + k_forceScale * point->normalForce * point->normal;
435
//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));
438
if (settings->drawFrictionForces == 1)
440
//b2Vec2 tangent = b2Cross(point->normal, 1.0f);
441
//b2Vec2 p1 = point->position;
442
//b2Vec2 p2 = p1 + k_forceScale * point->tangentForce * tangent;
443
//DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f));