add event profiler, json profile dump, cleanup

This commit is contained in:
Irlan
2017-02-24 20:11:49 -03:00
parent e1038cfb31
commit 689425d9ef
64 changed files with 16135 additions and 531 deletions

View File

@ -22,7 +22,7 @@
// Implementation of the GJK (Gilbert-Johnson-Keerthi) algorithm
// using Voronoi regions and Barycentric coordinates.
u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
u32 b3_gjkCalls = 0, b3_gjkIters = 0, b3_gjkMaxIters = 0;
b3Vec3 b3Simplex::GetSearchDirection(const b3Vec3& Q) const
{

View File

@ -22,8 +22,8 @@
#include <stdarg.h>
#include <stdlib.h>
u32 b3_allocCalls;
u32 b3_maxAllocCalls;
u32 b3_allocCalls = 0;
u32 b3_maxAllocCalls = 0;
b3Version b3_version = { 1, 0, 0 };

View File

@ -242,8 +242,50 @@ void b3Body::ResetMass()
{
m_invMass = 1.0f / m_mass;
localCenter *= m_invMass;
// Center inertia about the center of mass.
m_I = b3MoveToCOM(m_I, m_mass, localCenter);
m_invI = b3Inverse(m_I);
m_worldInvI = b3RotateToFrame(m_invI, m_xf.rotation);
// Fix rotation.
if (m_flags & e_fixedRotationX)
{
m_invI.y.y = 0.0f;
m_invI.z.y = 0.0f;
m_invI.y.z = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.y.y = 0.0f;
m_worldInvI.z.y = 0.0f;
m_worldInvI.y.z = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationY)
{
m_invI.x.x = 0.0f;
m_invI.x.z = 0.0f;
m_invI.z.x = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.z = 0.0f;
m_worldInvI.z.x = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationZ)
{
m_invI.x.x = 0.0f;
m_invI.x.y = 0.0f;
m_invI.y.x = 0.0f;
m_invI.y.y = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.y = 0.0f;
m_worldInvI.y.x = 0.0f;
m_worldInvI.y.y = 0.0f;
}
}
else
{
@ -252,61 +294,6 @@ void b3Body::ResetMass()
m_invMass = 1.0f;
}
// Fix rotation.
if (m_flags & e_fixedRotationX)
{
m_I.y.y = 0.0f;
m_I.z.y = 0.0f;
m_I.y.z = 0.0f;
m_I.z.z = 0.0f;
m_invI.y.y = 0.0f;
m_invI.z.y = 0.0f;
m_invI.y.z = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.y.y = 0.0f;
m_worldInvI.z.y = 0.0f;
m_worldInvI.y.z = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationY)
{
m_I.x.x = 0.0f;
m_I.x.z = 0.0f;
m_I.z.x = 0.0f;
m_I.z.z = 0.0f;
m_invI.x.x = 0.0f;
m_invI.x.z = 0.0f;
m_invI.z.x = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.z = 0.0f;
m_worldInvI.z.x = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationZ)
{
m_I.x.x = 0.0f;
m_I.x.y = 0.0f;
m_I.y.x = 0.0f;
m_I.y.y = 0.0f;
m_invI.x.x = 0.0f;
m_invI.x.y = 0.0f;
m_invI.y.x = 0.0f;
m_invI.y.y = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.y = 0.0f;
m_worldInvI.y.x = 0.0f;
m_worldInvI.y.y = 0.0f;
}
// Move center of mass.
b3Vec3 oldCenter = m_sweep.worldCenter;
m_sweep.localCenter = localCenter;
@ -343,6 +330,88 @@ bool b3Body::ShouldCollide(const b3Body* other) const
return true;
}
void b3Body::GetMassData(b3MassData* data) const
{
data->mass = m_mass;
data->I = m_I;
data->center = m_sweep.localCenter;
}
void b3Body::SetMassData(const b3MassData* massData)
{
if (m_type != e_dynamicBody)
{
return;
}
m_invMass = 0.0f;
m_I.SetZero();
m_invI.SetZero();
m_worldInvI.SetZero();
m_mass = massData->mass;
if (m_mass > 0.0f)
{
m_invMass = 1.0f / m_mass;
m_I = b3MoveToCOM(massData->I, m_mass, massData->center);
m_invI = b3Inverse(m_I);
m_worldInvI = b3RotateToFrame(m_invI, m_xf.rotation);
if (m_flags & e_fixedRotationX)
{
m_invI.y.y = 0.0f;
m_invI.z.y = 0.0f;
m_invI.y.z = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.y.y = 0.0f;
m_worldInvI.z.y = 0.0f;
m_worldInvI.y.z = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationY)
{
m_invI.x.x = 0.0f;
m_invI.x.z = 0.0f;
m_invI.z.x = 0.0f;
m_invI.z.z = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.z = 0.0f;
m_worldInvI.z.x = 0.0f;
m_worldInvI.z.z = 0.0f;
}
if (m_flags & e_fixedRotationZ)
{
m_invI.x.x = 0.0f;
m_invI.x.y = 0.0f;
m_invI.y.x = 0.0f;
m_invI.y.y = 0.0f;
m_worldInvI.x.x = 0.0f;
m_worldInvI.x.y = 0.0f;
m_worldInvI.y.x = 0.0f;
m_worldInvI.y.y = 0.0f;
}
}
else
{
m_mass = 1.0f;
m_invMass = 1.0f;
}
// Move center of mass.
b3Vec3 oldCenter = m_sweep.worldCenter;
m_sweep.localCenter = massData->center;
m_sweep.worldCenter0 = m_sweep.worldCenter = b3Mul(m_xf, m_sweep.localCenter);
// Update center of mass velocity.
m_linearVelocity += b3Cross(m_angularVelocity, m_sweep.worldCenter - oldCenter);
}
void b3Body::SetType(b3BodyType type)
{
if (m_type == type)

View File

@ -22,6 +22,7 @@
#include <bounce/dynamics/shapes/shape.h>
#include <bounce/dynamics/body.h>
#include <bounce/dynamics/world_listeners.h>
#include <bounce/common/profiler.h>
b3ContactManager::b3ContactManager() :
m_convexBlocks(sizeof(b3ConvexContact)),
@ -166,6 +167,8 @@ void b3ContactManager::FindNewContacts()
void b3ContactManager::UpdateContacts()
{
B3_PROFILE("Update Contacts");
// Update the state of all contacts.
b3Contact* c = m_contactList.m_head;
while (c)

View File

@ -22,7 +22,7 @@
#include <bounce/dynamics/shapes/capsule_shape.h>
#include <bounce/collision/shapes/capsule.h>
bool b3AreParalell(const b3Capsule& hullA, const b3Capsule& hullB)
static bool b3AreParalell(const b3Capsule& hullA, const b3Capsule& hullB)
{
b3Vec3 E1 = hullA.vertices[1] - hullA.vertices[0];
float32 L1 = b3Length(E1);
@ -59,6 +59,34 @@ void b3CollideCapsuleAndCapsule(b3Manifold& manifold,
hullB.radius = sB->m_radius;
float32 totalRadius = hullA.radius + hullB.radius;
// todo return small distance output struct?
b3Vec3 pointA, pointB;
b3ClosestPointsOnSegments(&pointA, &pointB, hullA.vertices[0], hullA.vertices[1], hullB.vertices[0], hullB.vertices[1]);
float32 distance = b3Distance(pointA, pointB);
if (distance > totalRadius)
{
return;
}
if (distance > B3_EPSILON)
{
b3Vec3 normal = (pointB - pointA) / distance;
b3Vec3 center = 0.5f * (pointA + hullA.radius * normal + pointB - hullB.radius * normal);
manifold.pointCount = 1;
manifold.points[0].triangleKey = B3_NULL_TRIANGLE;
manifold.points[0].key = 0;
manifold.points[0].localNormal = b3MulT(xfA.rotation, normal);
manifold.points[0].localPoint = b3MulT(xfA, pointA);
manifold.points[0].localPoint2 = b3MulT(xfB, pointB);
manifold.center = center;
manifold.normal = normal;
manifold.tangent1 = b3Perp(normal);
manifold.tangent2 = b3Cross(manifold.tangent1, normal);
return;
}
if (b3AreParalell(hullA, hullB))
{
@ -108,36 +136,7 @@ void b3CollideCapsuleAndCapsule(b3Manifold& manifold,
manifold.normal = normal;
manifold.tangent1 = b3Perp(normal);
manifold.tangent2 = b3Cross(manifold.tangent1, normal);
return;
}
}
}
b3Vec3 pointA, pointB;
b3ClosestPointsOnSegments(&pointA, &pointB, hullA.vertices[0], hullA.vertices[1], hullB.vertices[0], hullB.vertices[1]);
if (b3DistanceSquared(pointA, pointB) > totalRadius * totalRadius)
{
return;
}
float32 distance = b3Distance(pointA, pointB);
if (distance > B3_EPSILON)
{
b3Vec3 normal = (pointB - pointA) / distance;
b3Vec3 center = 0.5f * (pointA + hullA.radius * normal + pointB - hullB.radius * normal);
manifold.pointCount = 1;
manifold.points[0].triangleKey = B3_NULL_TRIANGLE;
manifold.points[0].key = 0;
manifold.points[0].localNormal = b3MulT(xfA.rotation, normal);
manifold.points[0].localPoint = b3MulT(xfA, pointA);
manifold.points[0].localPoint2 = b3MulT(xfB, pointB);
manifold.center = center;
manifold.normal = normal;
manifold.tangent1 = b3Perp(normal);
manifold.tangent2 = b3Cross(manifold.tangent1, normal);
}
}

View File

@ -241,7 +241,7 @@ void b3CollideHulls(b3Manifold& manifold,
//
bool b3_enableConvexCache = true;
u32 b3_convexCalls, b3_convexCacheHits;
u32 b3_convexCalls = 0, b3_convexCacheHits = 0;
void b3CollideHullAndHull(b3Manifold& manifold,
const b3Transform& xfA, const b3HullShape* sA,

View File

@ -48,11 +48,13 @@ const b3Color b3Color_blue(0.0f, 0.0f, 1.0f);
const b3Color b3Color_yellow(1.0f, 1.0f, 0.0f);
const b3Color b3Color_pink(1.0f, 0.0f, 1.0f);
b3Draw* b3_debugDraw = NULL;
void b3World::DebugDraw() const
{
B3_ASSERT(m_debugDraw);
B3_ASSERT(b3_debugDraw);
u32 flags = m_debugDraw->m_flags;
u32 flags = b3_debugDraw->m_flags;
if (flags & b3Draw::e_centerOfMassesFlag)
{
@ -60,7 +62,7 @@ void b3World::DebugDraw() const
{
b3Transform xf = b->m_xf;
xf.position = b->m_sweep.worldCenter;
m_debugDraw->DrawTransform(xf);
b3_debugDraw->DrawTransform(xf);
}
}
@ -83,7 +85,7 @@ void b3World::DebugDraw() const
for (b3Shape* s = b->m_shapeList.m_head; s; s = s->m_next)
{
const b3AABB3& aabb = m_contactMan.m_broadPhase.GetAABB(s->m_broadPhaseID);
m_debugDraw->DrawAABB(aabb, b3Color_pink);
b3_debugDraw->DrawAABB(aabb, b3Color_pink);
}
}
}
@ -122,18 +124,18 @@ void b3World::DebugDraw() const
if (flags & b3Draw::e_contactPointsFlag)
{
m_debugDraw->DrawPoint(p, 4.0f, b3Color_yellow);
b3_debugDraw->DrawPoint(p, 4.0f, b3Color_yellow);
}
if (flags & b3Draw::e_contactNormalsFlag)
{
m_debugDraw->DrawSegment(p, p + n, b3Color_yellow);
b3_debugDraw->DrawSegment(p, p + n, b3Color_yellow);
}
if (flags & b3Draw::e_contactTangentsFlag)
{
m_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
m_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
b3_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
b3_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
}
}
@ -152,18 +154,18 @@ void b3World::DebugDraw() const
if (flags & b3Draw::e_contactPointsFlag)
{
m_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? b3Color_green : b3Color_red);
b3_debugDraw->DrawPoint(p, 4.0f, mp->persisting ? b3Color_green : b3Color_red);
}
if (flags & b3Draw::e_contactNormalsFlag)
{
m_debugDraw->DrawSegment(p, p + n, b3Color_white);
b3_debugDraw->DrawSegment(p, p + n, b3Color_white);
}
if (flags & b3Draw::e_contactTangentsFlag)
{
m_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
m_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
b3_debugDraw->DrawSegment(p, p + t1, b3Color_yellow);
b3_debugDraw->DrawSegment(p, p + t2, b3Color_yellow);
}
}
}
@ -179,7 +181,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const
{
const b3SphereShape* sphere = (b3SphereShape*)shape;
b3Vec3 p = xf * sphere->m_center;
m_debugDraw->DrawPoint(p, 4.0f, wireColor);
b3_debugDraw->DrawPoint(p, 4.0f, wireColor);
break;
}
case e_capsuleShape:
@ -187,9 +189,9 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const
const b3CapsuleShape* capsule = (b3CapsuleShape*)shape;
b3Vec3 p1 = xf * capsule->m_centers[0];
b3Vec3 p2 = xf * capsule->m_centers[1];
m_debugDraw->DrawPoint(p1, 4.0f, wireColor);
m_debugDraw->DrawPoint(p2, 4.0f, wireColor);
m_debugDraw->DrawSegment(p1, p2, wireColor);
b3_debugDraw->DrawPoint(p1, 4.0f, wireColor);
b3_debugDraw->DrawPoint(p2, 4.0f, wireColor);
b3_debugDraw->DrawSegment(p1, p2, wireColor);
break;
}
case e_hullShape:
@ -204,7 +206,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const
b3Vec3 p1 = xf * hull->vertices[edge->origin];
b3Vec3 p2 = xf * hull->vertices[twin->origin];
m_debugDraw->DrawSegment(p1, p2, wireColor);
b3_debugDraw->DrawSegment(p1, p2, wireColor);
}
break;
}
@ -220,7 +222,7 @@ void b3World::DrawShape(const b3Transform& xf, const b3Shape* shape) const
b3Vec3 p2 = xf * mesh->vertices[t->v2];
b3Vec3 p3 = xf * mesh->vertices[t->v3];
m_debugDraw->DrawTriangle(p1, p2, p3, wireColor);
b3_debugDraw->DrawTriangle(p1, p2, p3, wireColor);
}
break;
}
@ -240,31 +242,31 @@ void b3World::DrawJoint(const b3Joint* joint) const
case e_mouseJoint:
{
b3MouseJoint* o = (b3MouseJoint*)joint;
o->Draw(m_debugDraw);
o->Draw(b3_debugDraw);
break;
}
case e_springJoint:
{
b3SpringJoint* o = (b3SpringJoint*)joint;
o->Draw(m_debugDraw);
o->Draw(b3_debugDraw);
break;
}
case e_revoluteJoint:
{
b3RevoluteJoint* o = (b3RevoluteJoint*)joint;
o->Draw(m_debugDraw);
o->Draw(b3_debugDraw);
break;
}
case e_sphereJoint:
{
b3SphereJoint* o = (b3SphereJoint*)joint;
o->Draw(m_debugDraw);
o->Draw(b3_debugDraw);
break;
}
case e_coneJoint:
{
b3ConeJoint* o = (b3ConeJoint*)joint;
o->Draw(m_debugDraw);
o->Draw(b3_debugDraw);
break;
}
default:

View File

@ -24,7 +24,7 @@
#include <bounce/dynamics/contacts/contact.h>
#include <bounce/dynamics/contacts/contact_solver.h>
#include <bounce/common/memory/stack_allocator.h>
#include <bounce/common/time.h>
#include <bounce/common/profiler.h>
b3Island::b3Island(b3StackAllocator* allocator, u32 bodyCapacity, u32 contactCapacity, u32 jointCapacity)
{
@ -83,7 +83,7 @@ void b3Island::Add(b3Joint* j)
++m_jointCount;
}
void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32 velocityIterations, u32 positionIterations, u32 flags)
void b3Island::Solve(const b3Vec3& gravity, float32 dt, u32 velocityIterations, u32 positionIterations, u32 flags)
{
float32 h = dt;
@ -155,8 +155,8 @@ void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32
// 2. Initialize constraints
{
b3Time time;
B3_PROFILE("Initialize Constraints");
contactSolver.InitializeConstraints();
if (flags & e_warmStartBit)
@ -170,14 +170,11 @@ void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32
{
jointSolver.WarmStart();
}
time.Update();
profile->solver.initializeContacts = time.GetElapsedMilis();
}
// 3. Solve velocity constraints
{
b3Time time;
B3_PROFILE("Solve Velocity Constraints");
for (u32 i = 0; i < velocityIterations; ++i)
{
@ -189,9 +186,6 @@ void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32
{
contactSolver.StoreImpulses();
}
time.Update();
profile->solver.solveVelocity = time.GetElapsedMilis();
}
// 4. Integrate positions
@ -230,7 +224,7 @@ void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32
// 5. Solve position constraints
{
b3Time time;
B3_PROFILE("Solve Position Constraints");
bool positionsSolved = false;
for (u32 i = 0; i < positionIterations; ++i)
@ -244,9 +238,6 @@ void b3Island::Solve(b3Profile* profile, const b3Vec3& gravity, float32 dt, u32
break;
}
}
time.Update();
profile->solver.solvePosition = time.GetElapsedMilis();
}
// 6. Copy state buffers back to the bodies

View File

@ -105,6 +105,7 @@ const b3Vec3& b3MouseJoint::GetTarget() const
void b3MouseJoint::SetTarget(const b3Vec3& target)
{
m_worldTargetA = target;
GetBodyB()->SetAwake(true);
}
void b3MouseJoint::Draw(b3Draw* draw) const

View File

@ -24,7 +24,7 @@
#include <bounce/dynamics/contacts/contact.h>
#include <bounce/dynamics/joints/joint.h>
#include <bounce/dynamics/time_step.h>
#include <bounce/common/time.h>
#include <bounce/common/profiler.h>
extern u32 b3_allocCalls;
extern u32 b3_maxAllocCalls;
@ -34,7 +34,6 @@ b3World::b3World() : m_bodyBlocks(sizeof(b3Body))
b3_allocCalls = 0;
b3_maxAllocCalls = 0;
m_debugDraw = NULL;
memset(&m_profile, 0, sizeof(b3Profile));
m_flags = e_clearForcesFlag;
m_sleeping = false;
@ -68,11 +67,6 @@ void b3World::SetSleeping(bool flag)
}
}
void b3World::SetDebugDraw(b3Draw* debugDraw)
{
m_debugDraw = debugDraw;
}
b3Body* b3World::CreateBody(const b3BodyDef& def)
{
void* mem = m_bodyBlocks.Allocate();
@ -104,9 +98,7 @@ void b3World::DestroyJoint(b3Joint* j)
void b3World::Step(float32 dt, u32 velocityIterations, u32 positionIterations)
{
memset(&m_profile, 0, sizeof(b3Profile));
b3Time stepTime;
B3_PROFILE("Step");
if (m_flags & e_shapeAddedFlag)
{
@ -115,34 +107,22 @@ void b3World::Step(float32 dt, u32 velocityIterations, u32 positionIterations)
m_flags &= ~e_shapeAddedFlag;
}
// Update contacts. This is where some contacts might be destroyed.
m_contactMan.UpdateContacts();
// Integrate velocities, clear forces and torques, solve constraints, integrate positions.
if (dt > 0.0f)
{
// Update contacts. This is where some contacts might be destroyed.
b3Time time;
m_contactMan.UpdateContacts();
time.Update();
m_profile.collide.narrowphase = time.GetElapsedMilis();
Solve(dt, velocityIterations, positionIterations);
}
{
b3Time time;
if (dt > 0.0f)
{
Solve(dt, velocityIterations, positionIterations);
}
time.Update();
}
{
//todo
//SolveTOI
}
stepTime.Update();
m_profile.total = stepTime.GetElapsedMilis();
//SolveTOI
}
void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
{
B3_PROFILE("Solve");
// Clear all visited flags for the depth first search.
for (b3Body* b = m_bodyList.m_head; b; b = b->m_next)
{
@ -289,7 +269,7 @@ void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
}
// Integrate velocities, clear forces and torques, solve constraints, integrate positions.
island.Solve(&m_profile, externalForce, dt, velocityIterations, positionIterations, islandFlags);
island.Solve(externalForce, dt, velocityIterations, positionIterations, islandFlags);
// Allow static bodies to participate in other islands.
for (u32 i = 0; i < island.m_bodyCount; ++i)
@ -305,7 +285,8 @@ void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
m_stackAllocator.Free(stack);
{
b3Time time;
B3_PROFILE("Find New Pairs");
for (b3Body* b = m_bodyList.m_head; b; b = b->m_next)
{
// If a body didn't participate on a island then it didn't move
@ -319,13 +300,10 @@ void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
b->SynchronizeShapes();
}
// Notify the contacts the shapes may have been moved.
// Notify the contacts the AABBs may have been moved.
m_contactMan.SynchronizeShapes();
m_contactMan.FindNewContacts();
time.Update();
m_profile.collide.broadphase = time.GetElapsedMilis();
}
}

View File

@ -20,6 +20,7 @@
#include <glfw/glfw3.h>
#include <imgui/imgui.h>
#include <imgui/imgui_impl_glfw_gl3.h>
#include <testbed/tests/test.h>
GLFWwindow* g_window;
@ -28,6 +29,7 @@ Test* g_test;
u32 g_testCount;
Camera g_camera;
DebugDraw* g_debugDraw;
Profiler* g_profiler;
bool g_leftDown;
bool g_rightDown;
bool g_shiftDown;
@ -41,13 +43,13 @@ void WindowSize(int w, int h)
void MouseMove(GLFWwindow* w, double x, double y)
{
b3Vec2 p;
p.Set(float32(x), float32(y));
b3Vec2 ps;
ps.Set(float32(x), float32(y));
b3Vec2 dp = p - g_ps0;
g_ps0 = p;
b3Vec2 dp = ps - g_ps0;
g_ps0 = ps;
Ray3 pw = g_camera.ConvertScreenToWorld(p);
Ray3 pw = g_camera.ConvertScreenToWorld(ps);
float32 nx = b3Clamp(dp.x, -1.0f, 1.0f);
float32 ny = b3Clamp(dp.y, -1.0f, 1.0f);
@ -453,6 +455,9 @@ int main(int argc, char** args)
// Create UI
CreateInterface();
// Create profiler
g_profiler = new Profiler();
// Create renderer
g_debugDraw = new DebugDraw();
@ -476,6 +481,9 @@ int main(int argc, char** args)
// Destroy renderer
delete g_debugDraw;
// Destroy profiler
delete g_profiler;
// Destroy UI
DestroyInterface();

View File

@ -0,0 +1,217 @@
/*
* Copyright (c) 2016-2016 Irlan Robson http://www.irlan.net
*
* This software is provided 'as-is', without any express or implied
* warranty. In no event will the authors be held liable for any damages
* arising from the use of this software.
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
* 1. The origin of this software must not be misrepresented; you must not
* claim that you wrote the original software. If you use this software
* in a product, an acknowledgment in the product documentation would be
* appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
* misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/
#include <testbed/framework/profiler.h>
#include <bounce/common/profiler.h>
#include <bounce/common/time.h>
#include <bounce/common/template/queue.h>
struct Event
{
i32 tid;
i32 pid;
const char* name;
float64 t0;
float64 t1;
Event* parent;
};
static b3Time time;
static b3BoundedQueue<Event, 256> events;
static Event* top = NULL;
bool b3PushProfileScope(const char* name)
{
time.Update();
Event e;
e.tid = -1;
e.pid = -1;
e.t0 = time.GetCurrentMilis();
e.t1 = 0;
e.name = name;
e.parent = top;
Event* back = events.Push(e);
if (back)
{
top = back;
}
return back != NULL;
}
void b3PopProfileScope()
{
B3_ASSERT(top);
B3_ASSERT(top->t1 == 0);
time.Update();
top->t1 = time.GetCurrentMilis();
B3_ASSERT(top->t1 != 0);
top = top->parent;
}
void ProfileBegin()
{
B3_ASSERT(events.IsEmpty());
}
void ProfileEnd()
{
ProfileBeginEvents();
while (events.IsEmpty() == false)
{
const Event& e = events.Front();
events.Pop();
ProfileEvent(-1, -1, e.name, e.t0, e_begin);
ProfileEvent(-1, -1, e.name, e.t1, e_end);
ProfileEvent(-1, -1, e.name, e.t1 - e.t0);
}
B3_ASSERT(events.IsEmpty());
ProfileEndEvents();
}
//
#define PROFILER_SCREEN 1
#define PROFILER_JSON 2
#define PROFILER_OUTPUT PROFILER_SCREEN
#if PROFILER_OUTPUT == PROFILER_SCREEN
extern Profiler* g_profiler;
void ProfileBeginEvents()
{
}
void ProfileEvent(i32 tid, i32 pid, const char* name, float64 time, ProfileType type)
{
}
void ProfileEvent(i32 tid, i32 pid, const char* name, float64 elapsed)
{
g_profiler->Add(name, elapsed);
}
void ProfileEndEvents()
{
}
#elif PROFILER_OUTPUT == PROFILER_JSON
#include <rapidjson/filewritestream.h>
#include <rapidjson/writer.h>
using namespace rapidjson;
static FILE* file = NULL;
static FileWriteStream* stream = NULL;
static Writer<FileWriteStream>* writer = NULL;
#define STRING(x) String(x, sizeof(x) - 1)
void ProfileBeginEvents()
{
if (file)
{
return;
}
file = fopen("profile.json", "wt");
if (!file)
{
return;
}
static char buffer[512];
stream = new FileWriteStream(file, buffer, sizeof(buffer));
writer = new Writer<FileWriteStream>(*stream);
writer->StartObject();
writer->STRING("traceEvents");
writer->StartArray();
}
void ProfileEvent(i32 tid, i32 pid, const char* name, float64 time, ProfileType type)
{
if (!writer)
{
return;
}
const char* phase = 0;
switch (type)
{
case ProfileType::e_begin: phase = "B"; break;
case ProfileType::e_end: phase = "E"; break;
default: B3_ASSERT(false);
}
float64 scale = 1000000;
writer->StartObject();
writer->STRING("pid"); writer->Int(pid);
writer->STRING("tid"); writer->Int(tid);
writer->STRING("ts"); writer->Int64((u64)(time * scale));
writer->STRING("ph"); writer->String(phase, 1);
writer->STRING("cat"); writer->STRING("physics");
writer->STRING("name"); writer->String(name, strlen(name));
writer->STRING("args"); writer->StartObject(); writer->EndObject();
writer->EndObject();
}
void ProfileEvent(i32 tid, i32 pid, const char* name, float64 elapsed)
{
}
void ProfileEndEvents()
{
if (!writer)
{
return;
}
writer->EndArray();
writer->EndObject();
delete writer;
writer = NULL;
delete stream;
stream = NULL;
fclose(file);
file = NULL;
}
#undef STRING
#else
#endif

View File

@ -22,10 +22,12 @@ extern u32 b3_allocCalls, b3_maxAllocCalls;
extern u32 b3_gjkCalls, b3_gjkIters, b3_gjkMaxIters;
extern u32 b3_convexCalls, b3_convexCacheHits;
extern bool b3_enableConvexCache;
extern b3Draw* b3_debugDraw;
extern Settings g_settings;
extern DebugDraw* g_debugDraw;
extern Camera g_camera;
extern Profiler* g_profiler;
Test::Test()
{
@ -36,19 +38,15 @@ Test::Test()
b3_convexCalls = 0;
b3_convexCacheHits = 0;
b3_enableConvexCache = g_settings.convexCache;
b3_debugDraw = g_debugDraw;
m_world.SetDebugDraw(g_debugDraw);
m_world.SetContactListener(this);
memset(&m_profile, 0, sizeof(b3Profile));
memset(&m_maxProfile, 0, sizeof(b3Profile));
g_camera.m_q = b3Quat(b3Vec3(0.0f, 1.0f, 0.0f), 0.15f * B3_PI);
g_camera.m_q = g_camera.m_q * b3Quat(b3Vec3(1.0f, 0.0f, 0.0f), -0.15f * B3_PI);
g_camera.m_zoom = 50.0f;
g_camera.m_center.SetZero();
g_settings.drawGrid = false;
m_rayHit.shape = NULL;
m_mouseJoint = NULL;
@ -350,19 +348,15 @@ void Test::Step()
b3_convexCalls = 0;
b3_convexCacheHits = 0;
b3_enableConvexCache = g_settings.convexCache;
// Step
ProfileBegin();
m_world.SetSleeping(g_settings.sleep);
m_world.SetWarmStart(g_settings.warmStart);
m_world.Step(dt, g_settings.velocityIterations, g_settings.positionIterations);
m_profile = m_world.GetProfile();
m_maxProfile.total = b3Max(m_maxProfile.total, m_profile.total);
m_maxProfile.collide.broadphase = b3Max(m_maxProfile.collide.broadphase, m_profile.collide.broadphase);
m_maxProfile.collide.narrowphase = b3Max(m_maxProfile.collide.narrowphase, m_profile.collide.narrowphase);
m_maxProfile.solver.solveVelocity = b3Max(m_maxProfile.solver.solveVelocity, m_profile.solver.solveVelocity);
m_maxProfile.solver.solvePosition = b3Max(m_maxProfile.solver.solvePosition, m_profile.solver.solvePosition);
ProfileEnd();
// Draw World
u32 drawFlags = 0;
@ -420,12 +414,14 @@ void Test::Step()
if (g_settings.drawProfile)
{
ImGui::Text("Step %.4f (%.4f) [ms]", m_profile.total, m_maxProfile.total);
ImGui::Text(" Insert Pairs %.4f (%.4f)", m_profile.collide.broadphase, m_maxProfile.collide.broadphase);
ImGui::Text(" Update Pairs %.4f (%.4f)", m_profile.collide.narrowphase, m_maxProfile.collide.narrowphase);
ImGui::Text(" Velocity Solver %.4f (%.4f)", m_profile.solver.solveVelocity, m_maxProfile.solver.solveVelocity);
ImGui::Text(" Position Solver %.4f (%.4f)", m_profile.solver.solvePosition, m_maxProfile.solver.solvePosition);
for (u32 i = 0; i < g_profiler->m_records.Count(); ++i)
{
const ProfileRecord& r = g_profiler->m_records[i];
ImGui::Text("%s %.4f (%.4f) [ms]", r.name, r.elapsed, r.maxElapsed);
}
}
g_profiler->Clear();
ImGui::End();
}

View File

@ -25,6 +25,8 @@
#include <testbed/tests/capsule_collision.h>
#include <testbed/tests/capsule_and_hull_collision.h>
#include <testbed/tests/hull_collision.h>
#include <testbed/tests/linear_motion.h>
#include <testbed/tests/angular_motion.h>
#include <testbed/tests/spring.h>
#include <testbed/tests/newton_cradle.h>
#include <testbed/tests/hinge_motor.h>
@ -57,6 +59,8 @@ TestEntry g_tests[] =
{ "Capsule Collision", &CapsuleCollision::Create },
{ "Capsule and Hull Collision", &CapsuleAndHull::Create },
{ "Hull Collision", &HullAndHull::Create },
{ "Linear Motion", &LinearMotion::Create },
{ "Angular Motion", &AngularMotion::Create },
{ "Springs", &Spring::Create },
{ "Newton's Cradle", &NewtonCradle::Create },
{ "Hinge Motor", &HingeMotor::Create },