add event profiler, json profile dump, cleanup
This commit is contained in:
@ -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
|
||||
{
|
||||
|
@ -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 };
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
||||
|
217
src/testbed/framework/profiler.cpp
Normal file
217
src/testbed/framework/profiler.cpp
Normal 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
|
@ -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();
|
||||
}
|
||||
|
@ -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 },
|
||||
|
Reference in New Issue
Block a user