2005-07-16 09:58:01 +00:00
|
|
|
/*
|
|
|
|
* Copyright (c) 2005 Erwin Coumans http://www.erwincoumans.com
|
|
|
|
*
|
|
|
|
* Permission to use, copy, modify, distribute and sell this software
|
|
|
|
* and its documentation for any purpose is hereby granted without fee,
|
|
|
|
* provided that the above copyright notice appear in all copies.
|
|
|
|
* Erwin Coumans makes no representations about the suitability
|
|
|
|
* of this software for any purpose.
|
|
|
|
* It is provided "as is" without express or implied warranty.
|
|
|
|
*/
|
|
|
|
#include "SimpleConstraintSolver.h"
|
|
|
|
#include "NarrowPhaseCollision/PersistentManifold.h"
|
|
|
|
#include "Dynamics/RigidBody.h"
|
|
|
|
#include "ContactConstraint.h"
|
|
|
|
#include "Solve2LinearConstraint.h"
|
|
|
|
#include "ContactSolverInfo.h"
|
|
|
|
#include "Dynamics/BU_Joint.h"
|
|
|
|
#include "Dynamics/ContactJoint.h"
|
2005-07-29 18:14:41 +00:00
|
|
|
#include "IDebugDraw.h"
|
2005-07-16 09:58:01 +00:00
|
|
|
|
|
|
|
//debugging
|
|
|
|
bool doApplyImpulse = true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool useImpulseFriction = true;//true;//false;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//iterative lcp and penalty method
|
2005-07-29 18:14:41 +00:00
|
|
|
float SimpleConstraintSolver::SolveGroup(PersistentManifold** manifoldPtr, int numManifolds,const ContactSolverInfo& infoGlobal,IDebugDraw* debugDrawer)
|
2005-07-16 09:58:01 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
ContactSolverInfo info = infoGlobal;
|
|
|
|
|
|
|
|
int numiter = infoGlobal.m_numIterations;
|
|
|
|
|
|
|
|
float substep = infoGlobal.m_timeStep / float(numiter);
|
|
|
|
|
|
|
|
for (int i = 0;i<numiter;i++)
|
|
|
|
{
|
|
|
|
for (int j=0;j<numManifolds;j++)
|
|
|
|
{
|
2005-08-12 13:42:00 +00:00
|
|
|
int k=j;
|
|
|
|
if (i % 2)
|
|
|
|
k = numManifolds-1-j;
|
|
|
|
|
|
|
|
Solve(manifoldPtr[k],info,i,debugDrawer);
|
2005-07-16 09:58:01 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
return 0.f;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
float penetrationResolveFactor = 0.9f;
|
|
|
|
|
|
|
|
|
2005-07-29 18:14:41 +00:00
|
|
|
float SimpleConstraintSolver::Solve(PersistentManifold* manifoldPtr, const ContactSolverInfo& info,int iter,IDebugDraw* debugDrawer)
|
2005-07-16 09:58:01 +00:00
|
|
|
{
|
|
|
|
|
|
|
|
RigidBody* body0 = (RigidBody*)manifoldPtr->GetBody0();
|
|
|
|
RigidBody* body1 = (RigidBody*)manifoldPtr->GetBody1();
|
|
|
|
|
|
|
|
float maxImpulse = 0.f;
|
|
|
|
|
|
|
|
|
|
|
|
float invNumIterFl = 1.f / float(info.m_numIterations);
|
|
|
|
|
|
|
|
float timeSubStep = info.m_timeStep * invNumIterFl;
|
|
|
|
|
|
|
|
//only necessary to refresh the manifold once (first iteration). The integration is done outside the loop
|
|
|
|
if (iter == 0)
|
|
|
|
{
|
|
|
|
manifoldPtr->RefreshContactPoints(body0->getCenterOfMassTransform(),body1->getCenterOfMassTransform());
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
const int numpoints = manifoldPtr->GetNumContacts();
|
|
|
|
|
2005-07-29 18:14:41 +00:00
|
|
|
SimdVector3 color(0,1,0);
|
2005-07-16 09:58:01 +00:00
|
|
|
for (int i=0;i<numpoints ;i++)
|
|
|
|
{
|
|
|
|
|
|
|
|
int j=i;
|
|
|
|
if (iter % 2)
|
|
|
|
j = numpoints-1-i;
|
|
|
|
else
|
|
|
|
j=i;
|
|
|
|
|
|
|
|
ManifoldPoint& cp = manifoldPtr->GetContactPoint(j);
|
2005-07-29 18:14:41 +00:00
|
|
|
|
2005-08-12 13:42:00 +00:00
|
|
|
if (iter == 0)
|
2005-07-16 09:58:01 +00:00
|
|
|
{
|
2005-08-12 13:42:00 +00:00
|
|
|
if (debugDrawer)
|
|
|
|
debugDrawer->DrawContactPoint(cp.m_positionWorldOnB,cp.m_normalWorldOnB,cp.GetDistance(),cp.GetLifeTime(),color);
|
|
|
|
}
|
2005-07-16 09:58:01 +00:00
|
|
|
|
2005-08-12 13:42:00 +00:00
|
|
|
{
|
2005-07-16 09:58:01 +00:00
|
|
|
|
|
|
|
|
2005-08-12 13:42:00 +00:00
|
|
|
float actualDist = cp.GetDistance();
|
|
|
|
#define MAXPENETRATIONPERFRAME -0.2f
|
|
|
|
float dist = actualDist< MAXPENETRATIONPERFRAME? MAXPENETRATIONPERFRAME:actualDist;
|
2005-07-16 09:58:01 +00:00
|
|
|
|
|
|
|
|
2005-08-12 13:42:00 +00:00
|
|
|
float impulse = resolveSingleCollisionWithFriction(
|
|
|
|
*body0,
|
2005-07-16 09:58:01 +00:00
|
|
|
cp.GetPositionWorldOnA(),
|
|
|
|
*body1,
|
|
|
|
cp.GetPositionWorldOnB(),
|
2005-08-12 13:42:00 +00:00
|
|
|
dist,
|
2005-07-16 09:58:01 +00:00
|
|
|
cp.m_normalWorldOnB,
|
|
|
|
info);
|
2005-08-12 13:42:00 +00:00
|
|
|
|
2005-07-16 09:58:01 +00:00
|
|
|
if (iter == 0)
|
|
|
|
{
|
|
|
|
cp.m_appliedImpulse = impulse;
|
|
|
|
} else
|
|
|
|
{
|
|
|
|
cp.m_appliedImpulse += impulse;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (maxImpulse < impulse)
|
|
|
|
maxImpulse = impulse;
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return maxImpulse;
|
|
|
|
}
|