~ubuntu-branches/ubuntu/vivid/emscripten/vivid

« back to all changes in this revision

Viewing changes to tests/box2d/Testbed/Framework/Test.cpp

  • Committer: Package Import Robot
  • Author(s): Sylvestre Ledru
  • Date: 2013-05-02 13:11:51 UTC
  • Revision ID: package-import@ubuntu.com-20130502131151-q8dvteqr1ef2x7xz
Tags: upstream-1.4.1~20130504~adb56cb
ImportĀ upstreamĀ versionĀ 1.4.1~20130504~adb56cb

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
* Copyright (c) 2006-2009 Erin Catto http://www.box2d.org
 
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
#include "Test.h"
 
20
#include <cstdio>
 
21
using namespace std;
 
22
 
 
23
void DestructionListener::SayGoodbye(b2Joint* joint)
 
24
{
 
25
        if (test->m_mouseJoint == joint)
 
26
        {
 
27
                test->m_mouseJoint = NULL;
 
28
        }
 
29
        else
 
30
        {
 
31
                test->JointDestroyed(joint);
 
32
        }
 
33
}
 
34
 
 
35
Test::Test()
 
36
{
 
37
        b2Vec2 gravity;
 
38
        gravity.Set(0.0f, -10.0f);
 
39
        m_world = new b2World(gravity);
 
40
        m_bomb = NULL;
 
41
        m_textLine = 30;
 
42
        m_mouseJoint = NULL;
 
43
        m_pointCount = 0;
 
44
 
 
45
        m_destructionListener.test = this;
 
46
        m_world->SetDestructionListener(&m_destructionListener);
 
47
        m_world->SetContactListener(this);
 
48
        m_world->SetDebugDraw(&m_debugDraw);
 
49
        
 
50
        m_bombSpawning = false;
 
51
 
 
52
        m_stepCount = 0;
 
53
 
 
54
        b2BodyDef bodyDef;
 
55
        m_groundBody = m_world->CreateBody(&bodyDef);
 
56
 
 
57
        memset(&m_maxProfile, 0, sizeof(b2Profile));
 
58
        memset(&m_totalProfile, 0, sizeof(b2Profile));
 
59
}
 
60
 
 
61
Test::~Test()
 
62
{
 
63
        // By deleting the world, we delete the bomb, mouse joint, etc.
 
64
        delete m_world;
 
65
        m_world = NULL;
 
66
}
 
67
 
 
68
void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold)
 
69
{
 
70
        const b2Manifold* manifold = contact->GetManifold();
 
71
 
 
72
        if (manifold->pointCount == 0)
 
73
        {
 
74
                return;
 
75
        }
 
76
 
 
77
        b2Fixture* fixtureA = contact->GetFixtureA();
 
78
        b2Fixture* fixtureB = contact->GetFixtureB();
 
79
 
 
80
        b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints];
 
81
        b2GetPointStates(state1, state2, oldManifold, manifold);
 
82
 
 
83
        b2WorldManifold worldManifold;
 
84
        contact->GetWorldManifold(&worldManifold);
 
85
 
 
86
        for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i)
 
87
        {
 
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];
 
94
                ++m_pointCount;
 
95
        }
 
96
}
 
97
 
 
98
void Test::DrawTitle(int x, int y, const char *string)
 
99
{
 
100
    m_debugDraw.DrawString(x, y, string);
 
101
}
 
102
 
 
103
class QueryCallback : public b2QueryCallback
 
104
{
 
105
public:
 
106
        QueryCallback(const b2Vec2& point)
 
107
        {
 
108
                m_point = point;
 
109
                m_fixture = NULL;
 
110
        }
 
111
 
 
112
        bool ReportFixture(b2Fixture* fixture)
 
113
        {
 
114
                b2Body* body = fixture->GetBody();
 
115
                if (body->GetType() == b2_dynamicBody)
 
116
                {
 
117
                        bool inside = fixture->TestPoint(m_point);
 
118
                        if (inside)
 
119
                        {
 
120
                                m_fixture = fixture;
 
121
 
 
122
                                // We are done, terminate the query.
 
123
                                return false;
 
124
                        }
 
125
                }
 
126
 
 
127
                // Continue the query.
 
128
                return true;
 
129
        }
 
130
 
 
131
        b2Vec2 m_point;
 
132
        b2Fixture* m_fixture;
 
133
};
 
134
 
 
135
void Test::MouseDown(const b2Vec2& p)
 
136
{
 
137
        m_mouseWorld = p;
 
138
        
 
139
        if (m_mouseJoint != NULL)
 
140
        {
 
141
                return;
 
142
        }
 
143
 
 
144
        // Make a small box.
 
145
        b2AABB aabb;
 
146
        b2Vec2 d;
 
147
        d.Set(0.001f, 0.001f);
 
148
        aabb.lowerBound = p - d;
 
149
        aabb.upperBound = p + d;
 
150
 
 
151
        // Query the world for overlapping shapes.
 
152
        QueryCallback callback(p);
 
153
        m_world->QueryAABB(&callback, aabb);
 
154
 
 
155
        if (callback.m_fixture)
 
156
        {
 
157
                b2Body* body = callback.m_fixture->GetBody();
 
158
                b2MouseJointDef md;
 
159
                md.bodyA = m_groundBody;
 
160
                md.bodyB = body;
 
161
                md.target = p;
 
162
                md.maxForce = 1000.0f * body->GetMass();
 
163
                m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&md);
 
164
                body->SetAwake(true);
 
165
        }
 
166
}
 
167
 
 
168
void Test::SpawnBomb(const b2Vec2& worldPt)
 
169
{
 
170
        m_bombSpawnPoint = worldPt;
 
171
        m_bombSpawning = true;
 
172
}
 
173
    
 
174
void Test::CompleteBombSpawn(const b2Vec2& p)
 
175
{
 
176
        if (m_bombSpawning == false)
 
177
        {
 
178
                return;
 
179
        }
 
180
 
 
181
        const float multiplier = 30.0f;
 
182
        b2Vec2 vel = m_bombSpawnPoint - p;
 
183
        vel *= multiplier;
 
184
        LaunchBomb(m_bombSpawnPoint,vel);
 
185
        m_bombSpawning = false;
 
186
}
 
187
 
 
188
void Test::ShiftMouseDown(const b2Vec2& p)
 
189
{
 
190
        m_mouseWorld = p;
 
191
        
 
192
        if (m_mouseJoint != NULL)
 
193
        {
 
194
                return;
 
195
        }
 
196
 
 
197
        SpawnBomb(p);
 
198
}
 
199
 
 
200
void Test::MouseUp(const b2Vec2& p)
 
201
{
 
202
        if (m_mouseJoint)
 
203
        {
 
204
                m_world->DestroyJoint(m_mouseJoint);
 
205
                m_mouseJoint = NULL;
 
206
        }
 
207
        
 
208
        if (m_bombSpawning)
 
209
        {
 
210
                CompleteBombSpawn(p);
 
211
        }
 
212
}
 
213
 
 
214
void Test::MouseMove(const b2Vec2& p)
 
215
{
 
216
        m_mouseWorld = p;
 
217
        
 
218
        if (m_mouseJoint)
 
219
        {
 
220
                m_mouseJoint->SetTarget(p);
 
221
        }
 
222
}
 
223
 
 
224
void Test::LaunchBomb()
 
225
{
 
226
        b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f);
 
227
        b2Vec2 v = -5.0f * p;
 
228
        LaunchBomb(p, v);
 
229
}
 
230
 
 
231
void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity)
 
232
{
 
233
        if (m_bomb)
 
234
        {
 
235
                m_world->DestroyBody(m_bomb);
 
236
                m_bomb = NULL;
 
237
        }
 
238
 
 
239
        b2BodyDef bd;
 
240
        bd.type = b2_dynamicBody;
 
241
        bd.position = position;
 
242
        bd.bullet = true;
 
243
        m_bomb = m_world->CreateBody(&bd);
 
244
        m_bomb->SetLinearVelocity(velocity);
 
245
        
 
246
        b2CircleShape circle;
 
247
        circle.m_radius = 0.3f;
 
248
 
 
249
        b2FixtureDef fd;
 
250
        fd.shape = &circle;
 
251
        fd.density = 20.0f;
 
252
        fd.restitution = 0.0f;
 
253
        
 
254
        b2Vec2 minV = position - b2Vec2(0.3f,0.3f);
 
255
        b2Vec2 maxV = position + b2Vec2(0.3f,0.3f);
 
256
        
 
257
        b2AABB aabb;
 
258
        aabb.lowerBound = minV;
 
259
        aabb.upperBound = maxV;
 
260
 
 
261
        m_bomb->CreateFixture(&fd);
 
262
}
 
263
 
 
264
void Test::Step(Settings* settings)
 
265
{
 
266
        float32 timeStep = settings->hz > 0.0f ? 1.0f / settings->hz : float32(0.0f);
 
267
 
 
268
        if (settings->pause)
 
269
        {
 
270
                if (settings->singleStep)
 
271
                {
 
272
                        settings->singleStep = 0;
 
273
                }
 
274
                else
 
275
                {
 
276
                        timeStep = 0.0f;
 
277
                }
 
278
 
 
279
                m_debugDraw.DrawString(5, m_textLine, "****PAUSED****");
 
280
                m_textLine += 15;
 
281
        }
 
282
 
 
283
        uint32 flags = 0;
 
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);
 
290
 
 
291
        m_world->SetWarmStarting(settings->enableWarmStarting > 0);
 
292
        m_world->SetContinuousPhysics(settings->enableContinuous > 0);
 
293
        m_world->SetSubStepping(settings->enableSubStepping > 0);
 
294
 
 
295
        m_pointCount = 0;
 
296
 
 
297
        m_world->Step(timeStep, settings->velocityIterations, settings->positionIterations);
 
298
 
 
299
        m_world->DrawDebugData();
 
300
 
 
301
        if (timeStep > 0.0f)
 
302
        {
 
303
                ++m_stepCount;
 
304
        }
 
305
 
 
306
        if (settings->drawStats)
 
307
        {
 
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);
 
312
                m_textLine += 15;
 
313
 
 
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);
 
319
                m_textLine += 15;
 
320
        }
 
321
 
 
322
        // Track maximum profile times
 
323
        {
 
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);
 
333
 
 
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;
 
342
        }
 
343
 
 
344
        if (settings->drawProfile)
 
345
        {
 
346
                const b2Profile& p = m_world->GetProfile();
 
347
 
 
348
                b2Profile aveProfile;
 
349
                memset(&aveProfile, 0, sizeof(b2Profile));
 
350
                if (m_stepCount > 0)
 
351
                {
 
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;
 
361
                }
 
362
 
 
363
                m_debugDraw.DrawString(5, m_textLine, "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, m_maxProfile.step);
 
364
                m_textLine += 15;
 
365
                m_debugDraw.DrawString(5, m_textLine, "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, m_maxProfile.collide);
 
366
                m_textLine += 15;
 
367
                m_debugDraw.DrawString(5, m_textLine, "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, m_maxProfile.solve);
 
368
                m_textLine += 15;
 
369
                m_debugDraw.DrawString(5, m_textLine, "solve init [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveInit, aveProfile.solveInit, m_maxProfile.solveInit);
 
370
                m_textLine += 15;
 
371
                m_debugDraw.DrawString(5, m_textLine, "solve velocity [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveVelocity, aveProfile.solveVelocity, m_maxProfile.solveVelocity);
 
372
                m_textLine += 15;
 
373
                m_debugDraw.DrawString(5, m_textLine, "solve position [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solvePosition, aveProfile.solvePosition, m_maxProfile.solvePosition);
 
374
                m_textLine += 15;
 
375
                m_debugDraw.DrawString(5, m_textLine, "solveTOI [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveTOI, aveProfile.solveTOI, m_maxProfile.solveTOI);
 
376
                m_textLine += 15;
 
377
                m_debugDraw.DrawString(5, m_textLine, "broad-phase [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.broadphase, aveProfile.broadphase, m_maxProfile.broadphase);
 
378
                m_textLine += 15;
 
379
        }
 
380
 
 
381
        if (m_mouseJoint)
 
382
        {
 
383
                b2Vec2 p1 = m_mouseJoint->GetAnchorB();
 
384
                b2Vec2 p2 = m_mouseJoint->GetTarget();
 
385
 
 
386
                b2Color c;
 
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);
 
390
 
 
391
                c.Set(0.8f, 0.8f, 0.8f);
 
392
                m_debugDraw.DrawSegment(p1, p2, c);
 
393
        }
 
394
        
 
395
        if (m_bombSpawning)
 
396
        {
 
397
                b2Color c;
 
398
                c.Set(0.0f, 0.0f, 1.0f);
 
399
                m_debugDraw.DrawPoint(m_bombSpawnPoint, 4.0f, c);
 
400
 
 
401
                c.Set(0.8f, 0.8f, 0.8f);
 
402
                m_debugDraw.DrawSegment(m_mouseWorld, m_bombSpawnPoint, c);
 
403
        }
 
404
 
 
405
        if (settings->drawContactPoints)
 
406
        {
 
407
                //const float32 k_impulseScale = 0.1f;
 
408
                const float32 k_axisScale = 0.3f;
 
409
 
 
410
                for (int32 i = 0; i < m_pointCount; ++i)
 
411
                {
 
412
                        ContactPoint* point = m_points + i;
 
413
 
 
414
                        if (point->state == b2_addState)
 
415
                        {
 
416
                                // Add
 
417
                                m_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f));
 
418
                        }
 
419
                        else if (point->state == b2_persistState)
 
420
                        {
 
421
                                // Persist
 
422
                                m_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f));
 
423
                        }
 
424
 
 
425
                        if (settings->drawContactNormals == 1)
 
426
                        {
 
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));
 
430
                        }
 
431
                        else if (settings->drawContactForces == 1)
 
432
                        {
 
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));
 
436
                        }
 
437
 
 
438
                        if (settings->drawFrictionForces == 1)
 
439
                        {
 
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));
 
444
                        }
 
445
                }
 
446
        }
 
447
}