fix mouse joint, draw center of mass, cleanup
This commit is contained in:
@ -29,27 +29,6 @@ struct b3Velocity;
|
|||||||
struct b3Position;
|
struct b3Position;
|
||||||
struct b3Profile;
|
struct b3Profile;
|
||||||
|
|
||||||
struct b3IslandBody
|
|
||||||
{
|
|
||||||
b3Body* b;
|
|
||||||
u32 id;
|
|
||||||
bool visited;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct b3IslandJoint
|
|
||||||
{
|
|
||||||
b3Joint* j;
|
|
||||||
u32 id;
|
|
||||||
bool visited;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct b3IslandContact
|
|
||||||
{
|
|
||||||
b3Contact* c;
|
|
||||||
u32 id;
|
|
||||||
bool visited;
|
|
||||||
};
|
|
||||||
|
|
||||||
class b3Island
|
class b3Island
|
||||||
{
|
{
|
||||||
public :
|
public :
|
||||||
|
@ -80,6 +80,7 @@ private:
|
|||||||
u32 m_indexB;
|
u32 m_indexB;
|
||||||
float32 m_mB;
|
float32 m_mB;
|
||||||
b3Mat33 m_iB;
|
b3Mat33 m_iB;
|
||||||
|
b3Vec3 m_localCenterB;
|
||||||
b3Mat33 m_mass;
|
b3Mat33 m_mass;
|
||||||
b3Vec3 m_rB;
|
b3Vec3 m_rB;
|
||||||
b3Vec3 m_impulse;
|
b3Vec3 m_impulse;
|
||||||
|
@ -103,7 +103,7 @@ public:
|
|||||||
hull.m_hull = &m_cylinderHull;
|
hull.m_hull = &m_cylinderHull;
|
||||||
|
|
||||||
b3ShapeDef sdef;
|
b3ShapeDef sdef;
|
||||||
sdef.density = 0.2f;
|
sdef.density = 1.0f;
|
||||||
sdef.friction = 0.3f;
|
sdef.friction = 0.3f;
|
||||||
sdef.shape = &hull;
|
sdef.shape = &hull;
|
||||||
|
|
||||||
|
@ -24,6 +24,18 @@ void b3Hull::Validate() const
|
|||||||
{
|
{
|
||||||
Validate(faces + i);
|
Validate(faces + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < edgeCount; i += 2)
|
||||||
|
{
|
||||||
|
const b3HalfEdge* edge = edges + i;
|
||||||
|
const b3HalfEdge* twin = edges + i + 1;
|
||||||
|
|
||||||
|
b3Vec3 A = vertices[edge->origin];
|
||||||
|
b3Vec3 B = vertices[twin->origin];
|
||||||
|
|
||||||
|
// Ensure each edge has non-zero length.
|
||||||
|
B3_ASSERT(b3DistanceSquared(A, B) > B3_EPSILON * B3_EPSILON);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3Hull::Validate(const b3Face* face) const
|
void b3Hull::Validate(const b3Face* face) const
|
||||||
|
@ -179,35 +179,44 @@ void b3Body::SynchronizeTransform()
|
|||||||
|
|
||||||
void b3Body::SynchronizeShapes()
|
void b3Body::SynchronizeShapes()
|
||||||
{
|
{
|
||||||
b3Transform xf0;
|
b3Transform xf1;
|
||||||
xf0.position = m_sweep.worldCenter0;
|
xf1.position = m_sweep.worldCenter0;
|
||||||
xf0.rotation = b3ConvertQuatToRot(m_sweep.orientation0);
|
xf1.rotation = b3ConvertQuatToRot(m_sweep.orientation0);
|
||||||
|
|
||||||
b3Transform xf1 = m_xf;
|
b3Transform xf2 = m_xf;
|
||||||
|
|
||||||
b3Vec3 displacement = xf1.position - xf0.position;
|
b3Vec3 displacement = xf2.position - xf1.position;
|
||||||
|
|
||||||
// Update the AABBs of all shapes.
|
// Update all shape AABBs.
|
||||||
|
b3BroadPhase* broadPhase = &m_world->m_contactMan.m_broadPhase;
|
||||||
for (b3Shape* s = m_shapeList.m_head; s; s = s->m_next)
|
for (b3Shape* s = m_shapeList.m_head; s; s = s->m_next)
|
||||||
{
|
{
|
||||||
b3AABB3 aabb;
|
// Compute an AABB that encloses the swept shape AABB.
|
||||||
s->ComputeAABB(&aabb, xf1);
|
b3AABB3 aabb1, aabb2;
|
||||||
m_world->m_contactMan.m_broadPhase.MoveProxy(s->m_broadPhaseID, aabb, displacement);
|
s->ComputeAABB(&aabb1, xf1);
|
||||||
|
s->ComputeAABB(&aabb2, xf2);
|
||||||
|
|
||||||
|
b3AABB3 aabb = b3Combine(aabb1, aabb2);
|
||||||
|
|
||||||
|
broadPhase->MoveProxy(s->m_broadPhaseID, aabb, displacement);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3Body::ResetMass()
|
void b3Body::ResetMass()
|
||||||
{
|
{
|
||||||
// Set mass and inertia tensor to zero.
|
|
||||||
m_mass = 0.0f;
|
m_mass = 0.0f;
|
||||||
m_invMass = 0.0f;
|
m_invMass = 0.0f;
|
||||||
m_I.SetZero();
|
m_I.SetZero();
|
||||||
m_invI.SetZero();
|
m_invI.SetZero();
|
||||||
m_worldInvI.SetZero();
|
m_worldInvI.SetZero();
|
||||||
|
m_sweep.localCenter.SetZero();
|
||||||
|
|
||||||
// Static and kinematic bodies have zero mass.
|
// Static and kinematic bodies have zero mass.
|
||||||
if (m_type == e_staticBody || m_type == e_kinematicBody)
|
if (m_type == e_staticBody || m_type == e_kinematicBody)
|
||||||
{
|
{
|
||||||
|
m_sweep.worldCenter0 = m_xf.position;
|
||||||
|
m_sweep.worldCenter = m_xf.position;
|
||||||
|
m_sweep.orientation0 = m_sweep.orientation;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -238,7 +247,7 @@ void b3Body::ResetMass()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Dynamic bodies have positive mass.
|
// Force all dynamic bodies to have positive mass.
|
||||||
m_mass = 1.0f;
|
m_mass = 1.0f;
|
||||||
m_invMass = 1.0f;
|
m_invMass = 1.0f;
|
||||||
}
|
}
|
||||||
@ -298,15 +307,14 @@ void b3Body::ResetMass()
|
|||||||
m_worldInvI.y.y = 0.0f;
|
m_worldInvI.y.y = 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update center of mass.
|
// Move center of mass.
|
||||||
|
b3Vec3 oldCenter = m_sweep.worldCenter;
|
||||||
m_sweep.localCenter = localCenter;
|
m_sweep.localCenter = localCenter;
|
||||||
|
m_sweep.worldCenter = b3Mul(m_xf, m_sweep.localCenter);
|
||||||
b3Vec3 worldCenter0 = m_sweep.worldCenter;
|
|
||||||
m_sweep.worldCenter = b3Mul(m_xf, localCenter);
|
|
||||||
m_sweep.worldCenter0 = m_sweep.worldCenter;
|
m_sweep.worldCenter0 = m_sweep.worldCenter;
|
||||||
|
|
||||||
// Update center of mass velocity.
|
// Update center of mass velocity.
|
||||||
m_linearVelocity += b3Cross(m_angularVelocity, m_sweep.worldCenter - worldCenter0);
|
m_linearVelocity += b3Cross(m_angularVelocity, m_sweep.worldCenter - oldCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool b3Body::ShouldCollide(const b3Body* other) const
|
bool b3Body::ShouldCollide(const b3Body* other) const
|
||||||
|
@ -104,6 +104,7 @@ void b3RebuildFaceContact(b3Manifold& manifold,
|
|||||||
b3FaceQuery query;
|
b3FaceQuery query;
|
||||||
query.index = indexA;
|
query.index = indexA;
|
||||||
|
|
||||||
|
// @todo Use heuristic (relative orientation) to increase performance.
|
||||||
b3BuildFaceContact(manifold, xfA, hullA, xfB, hullB, query, flipNormal);
|
b3BuildFaceContact(manifold, xfA, hullA, xfB, hullB, query, flipNormal);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,7 +58,8 @@ void b3World::DebugDraw() const
|
|||||||
{
|
{
|
||||||
for (b3Body* b = m_bodyList.m_head; b; b = b->m_next)
|
for (b3Body* b = m_bodyList.m_head; b; b = b->m_next)
|
||||||
{
|
{
|
||||||
const b3Transform& xf = b->GetTransform();
|
b3Transform xf = b->m_xf;
|
||||||
|
xf.position = b->m_sweep.worldCenter;
|
||||||
m_debugDraw->DrawTransform(xf);
|
m_debugDraw->DrawTransform(xf);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,19 +36,19 @@ void b3MouseJoint::InitializeConstraints(const b3SolverData* data)
|
|||||||
m_indexB = m_bodyB->m_islandID;
|
m_indexB = m_bodyB->m_islandID;
|
||||||
m_mB = m_bodyB->m_invMass;
|
m_mB = m_bodyB->m_invMass;
|
||||||
m_iB = m_bodyB->m_worldInvI;
|
m_iB = m_bodyB->m_worldInvI;
|
||||||
|
m_localCenterB = m_bodyB->m_sweep.localCenter;
|
||||||
|
|
||||||
b3Vec3 xB = data->positions[m_indexB].x;
|
b3Vec3 xB = data->positions[m_indexB].x;
|
||||||
b3Quat qB = data->positions[m_indexB].q;
|
b3Quat qB = data->positions[m_indexB].q;
|
||||||
|
|
||||||
b3Vec3 worldAnchorB = b3Mul(qB, m_localAnchorB) + xB;
|
// Compute the effective mass matrix.
|
||||||
|
m_rB = b3Mul(qB, m_localAnchorB - m_localCenterB);
|
||||||
m_C = worldAnchorB - m_worldTargetA;
|
|
||||||
m_rB = worldAnchorB - xB;
|
|
||||||
|
|
||||||
b3Mat33 M = b3Diagonal(m_mB);
|
b3Mat33 M = b3Diagonal(m_mB);
|
||||||
b3Mat33 RB = b3Skew(m_rB);
|
b3Mat33 RB = b3Skew(m_rB);
|
||||||
b3Mat33 RBT = b3Transpose(RB);
|
b3Mat33 RBT = b3Transpose(RB);
|
||||||
m_mass = M + RB * m_iB * RBT;
|
m_mass = M + RB * m_iB * RBT;
|
||||||
|
|
||||||
|
m_C = xB + m_rB - m_worldTargetA;
|
||||||
}
|
}
|
||||||
|
|
||||||
void b3MouseJoint::WarmStart(const b3SolverData* data)
|
void b3MouseJoint::WarmStart(const b3SolverData* data)
|
||||||
@ -64,19 +64,14 @@ void b3MouseJoint::SolveVelocityConstraints(const b3SolverData* data)
|
|||||||
|
|
||||||
b3Vec3 Cdot = vB + b3Cross(wB, m_rB);
|
b3Vec3 Cdot = vB + b3Cross(wB, m_rB);
|
||||||
|
|
||||||
b3Vec3 impulse = m_mass.Solve(-(Cdot + data->invdt * B3_BAUMGARTE * m_C));
|
b3Vec3 impulse = m_mass.Solve(-(Cdot + B3_BAUMGARTE * data->invdt * m_C));
|
||||||
b3Vec3 oldImpulse = m_impulse;
|
b3Vec3 oldImpulse = m_impulse;
|
||||||
m_impulse += impulse;
|
m_impulse += impulse;
|
||||||
|
|
||||||
// Prevent large reaction impulses.
|
|
||||||
float32 maxImpulse = data->dt * m_maxForce;
|
float32 maxImpulse = data->dt * m_maxForce;
|
||||||
float32 sqrImpulse = b3Dot(m_impulse, m_impulse);
|
if (b3Dot(m_impulse, m_impulse) > maxImpulse * maxImpulse)
|
||||||
if (sqrImpulse > maxImpulse * maxImpulse)
|
|
||||||
{
|
{
|
||||||
float32 ratio = maxImpulse / b3Sqrt(sqrImpulse);
|
m_impulse *= maxImpulse / b3Length(m_impulse);
|
||||||
m_impulse *= ratio;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impulse = m_impulse - oldImpulse;
|
impulse = m_impulse - oldImpulse;
|
||||||
|
|
||||||
vB += m_mB * impulse;
|
vB += m_mB * impulse;
|
||||||
|
@ -135,11 +135,7 @@ void b3HullShape::ComputeMass(b3MassData* massData, float32 density) const
|
|||||||
{
|
{
|
||||||
invVolume = 1.0f / volume;
|
invVolume = 1.0f / volume;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
invVolume = 0.0f;
|
|
||||||
}
|
|
||||||
|
|
||||||
diag = invVolume * diag;
|
diag = invVolume * diag;
|
||||||
offDiag = invVolume * offDiag;
|
offDiag = invVolume * offDiag;
|
||||||
|
|
||||||
|
@ -319,11 +319,11 @@ void b3World::Solve(float32 dt, u32 velocityIterations, u32 positionIterations)
|
|||||||
b->SynchronizeShapes();
|
b->SynchronizeShapes();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Notify the contacts the shapes may have moved.
|
// Notify the contacts the shapes may have been moved.
|
||||||
m_contactMan.SynchronizeShapes();
|
m_contactMan.SynchronizeShapes();
|
||||||
|
|
||||||
time.Update();
|
|
||||||
m_contactMan.FindNewContacts();
|
m_contactMan.FindNewContacts();
|
||||||
|
|
||||||
time.Update();
|
time.Update();
|
||||||
m_profile.collide.broadphase = time.GetElapsedMilis();
|
m_profile.collide.broadphase = time.GetElapsedMilis();
|
||||||
}
|
}
|
||||||
|
@ -207,12 +207,6 @@ void CreateInterface()
|
|||||||
ImGui_ImplGlfwGL3_Init(g_window, false);
|
ImGui_ImplGlfwGL3_Init(g_window, false);
|
||||||
ImGuiIO& io = ImGui::GetIO();
|
ImGuiIO& io = ImGui::GetIO();
|
||||||
io.Fonts[0].AddFontDefault();
|
io.Fonts[0].AddFontDefault();
|
||||||
|
|
||||||
ImGuiStyle& style = ImGui::GetStyle();
|
|
||||||
style.FrameRounding = style.GrabRounding = style.ScrollbarRounding = 2.0f;
|
|
||||||
style.FramePadding = ImVec2(4, 2);
|
|
||||||
style.DisplayWindowPadding = ImVec2(0, 0);
|
|
||||||
style.DisplaySafeAreaPadding = ImVec2(0, 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void DestroyInterface()
|
void DestroyInterface()
|
||||||
|
@ -358,9 +358,9 @@ void Test::MouseMove(const Ray3& pw)
|
|||||||
{
|
{
|
||||||
if (m_mouseJoint)
|
if (m_mouseJoint)
|
||||||
{
|
{
|
||||||
float32 hitFraction = m_rayHit.fraction;
|
float32 t = m_rayHit.fraction;
|
||||||
float32 w1 = 1.0f - hitFraction;
|
float32 w1 = 1.0f - t;
|
||||||
float32 w2 = hitFraction;
|
float32 w2 = t;
|
||||||
|
|
||||||
b3Vec3 target = w1 * pw.Start() + w2 * pw.End();
|
b3Vec3 target = w1 * pw.Start() + w2 * pw.End();
|
||||||
m_mouseJoint->SetTarget(target);
|
m_mouseJoint->SetTarget(target);
|
||||||
|
Reference in New Issue
Block a user