Implement simple body part drop strategy to resolve body

interpenetrations
This commit is contained in:
Benelot
2016-09-06 22:30:46 +02:00
parent dcfa5a3ee2
commit d9a2113b28

View File

@@ -52,7 +52,9 @@ static btScalar gLegLength = 0.45f;
static btScalar gForeLegLength = 0.75f; static btScalar gForeLegLength = 0.75f;
static btScalar gForeLegRadius = 0.08f; static btScalar gForeLegRadius = 0.08f;
class NN3DWalkers : public CommonRigidBodyBase void* GROUND_ID = (void*)1;
class NN3DWalkersExample : public CommonRigidBodyBase
{ {
btScalar m_Time; btScalar m_Time;
btScalar m_targetAccumulator; btScalar m_targetAccumulator;
@@ -63,7 +65,7 @@ class NN3DWalkers : public CommonRigidBodyBase
public: public:
NN3DWalkers(struct GUIHelperInterface* helper) NN3DWalkersExample(struct GUIHelperInterface* helper)
:CommonRigidBodyBase(helper), m_Time(0),m_motorStrength(0.5f),m_targetFrequency(3),m_targetAccumulator(0) :CommonRigidBodyBase(helper), m_Time(0),m_motorStrength(0.5f),m_targetFrequency(3),m_targetAccumulator(0)
{ {
@@ -72,7 +74,7 @@ public:
virtual void exitPhysics(); virtual void exitPhysics();
virtual ~NN3DWalkers() virtual ~NN3DWalkersExample()
{ {
} }
@@ -82,6 +84,44 @@ public:
void setMotorTargets(btScalar deltaTime); void setMotorTargets(btScalar deltaTime);
bool detectCollisions(){
bool collisionDetected = false;
if(m_dynamicsWorld){
m_dynamicsWorld->performDiscreteCollisionDetection(); // let the collisions be calculated
}
int numManifolds = m_dynamicsWorld->getDispatcher()->getNumManifolds();
for (int i=0;i<numManifolds;i++)
{
btPersistentManifold* contactManifold = m_dynamicsWorld->getDispatcher()->getManifoldByIndexInternal(i);
const btCollisionObject* obA = contactManifold->getBody0();
const btCollisionObject* obB = contactManifold->getBody1();
if(obA->getUserPointer() != GROUND_ID && obB->getUserPointer() != GROUND_ID){
int numContacts = contactManifold->getNumContacts();
for (int j=0;j<numContacts;j++)
{
collisionDetected = true;
btManifoldPoint& pt = contactManifold->getContactPoint(j);
if (pt.getDistance()<0.f)
{
const btVector3& ptA = pt.getPositionWorldOnA();
const btVector3& ptB = pt.getPositionWorldOnB();
const btVector3& normalOnB = pt.m_normalWorldOnB;
if(m_dynamicsWorld->getDebugDrawer()){
m_dynamicsWorld->getDebugDrawer()->drawSphere(pt.getPositionWorldOnA(), 0.1, btVector3(0., 0., 1.));
m_dynamicsWorld->getDebugDrawer()->drawSphere(pt.getPositionWorldOnB(), 0.1, btVector3(0., 0., 1.));
}
}
}
}
}
return collisionDetected;
}
void resetCamera() void resetCamera()
{ {
float dist = 11; float dist = 11;
@@ -94,7 +134,7 @@ public:
virtual void renderScene(); virtual void renderScene();
}; };
static NN3DWalkers* nn3DWalkers = NULL; static NN3DWalkersExample* nn3DWalkers = NULL;
#ifndef SIMD_PI_4 #ifndef SIMD_PI_4
#define SIMD_PI_4 0.5 * SIMD_HALF_PI #define SIMD_PI_4 0.5 * SIMD_HALF_PI
@@ -104,7 +144,6 @@ static NN3DWalkers* nn3DWalkers = NULL;
#define SIMD_PI_8 0.25 * SIMD_HALF_PI #define SIMD_PI_8 0.25 * SIMD_HALF_PI
#endif #endif
void* GROUND_ID = (void*)1;
bool RANDOM_MOVEMENT = false; bool RANDOM_MOVEMENT = false;
bool RANDOM_DIMENSIONS = false; bool RANDOM_DIMENSIONS = false;
@@ -135,8 +174,6 @@ class NNWalker
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,motionState,shape,localInertia); btRigidBody::btRigidBodyConstructionInfo rbInfo(mass,motionState,shape,localInertia);
btRigidBody* body = new btRigidBody(rbInfo); btRigidBody* body = new btRigidBody(rbInfo);
m_ownerWorld->addRigidBody(body);
return body; return body;
} }
@@ -156,7 +193,6 @@ public:
// //
// Setup geometry // Setup geometry
//
m_shapes[0] = new btCapsuleShape(gRootBodyRadius, gRootBodyHeight); // root body capsule m_shapes[0] = new btCapsuleShape(gRootBodyRadius, gRootBodyHeight); // root body capsule
int i; int i;
for ( i=0; i<NUM_LEGS; i++) for ( i=0; i<NUM_LEGS; i++)
@@ -167,7 +203,6 @@ public:
// //
// Setup rigid bodies // Setup rigid bodies
//
float rootAboveGroundHeight = gForeLegLength; float rootAboveGroundHeight = gForeLegLength;
btTransform bodyOffset; bodyOffset.setIdentity(); btTransform bodyOffset; bodyOffset.setIdentity();
bodyOffset.setOrigin(positionOffset); bodyOffset.setOrigin(positionOffset);
@@ -177,13 +212,11 @@ public:
btTransform transform; btTransform transform;
transform.setIdentity(); transform.setIdentity();
transform.setOrigin(localRootBodyPosition); transform.setOrigin(localRootBodyPosition);
if (bFixed) // if fixed body
{ m_bodies[0] = localCreateRigidBody(btScalar(bFixed?0.:1.), bodyOffset*transform, m_shapes[0]);
m_bodies[0] = localCreateRigidBody(btScalar(0.), bodyOffset*transform, m_shapes[0]); m_ownerWorld->addRigidBody(m_bodies[0]);
} else m_bodies[0]->setUserPointer(this);
{ m_bodyTouchSensorIndexMap.insert(std::pair<void*,int>(m_bodies[0], 0));
m_bodies[0] = localCreateRigidBody(btScalar(1.), bodyOffset*transform, m_shapes[0]);
}
btHingeConstraint* hingeC; btHingeConstraint* hingeC;
//btConeTwistConstraint* coneC; //btConeTwistConstraint* coneC;
@@ -206,15 +239,15 @@ public:
btVector3 kneeAxis = legDirection.cross(vUp); btVector3 kneeAxis = legDirection.cross(vUp);
transform.setRotation(btQuaternion(kneeAxis, SIMD_HALF_PI)); transform.setRotation(btQuaternion(kneeAxis, SIMD_HALF_PI));
m_bodies[1+2*i] = localCreateRigidBody(btScalar(1.), bodyOffset*transform, m_shapes[1+2*i]); m_bodies[1+2*i] = localCreateRigidBody(btScalar(1.), bodyOffset*transform, m_shapes[1+2*i]);
m_bodies[1+2*i]->setUserPointer(this);
m_bodyTouchSensorIndexMap.insert(std::pair<void*,int>(m_bodies[1+2*i],1+2*i));
// shin // shin
transform.setIdentity(); transform.setIdentity();
transform.setOrigin(btVector3(btScalar(footXUnitPosition*(gRootBodyRadius+gLegLength)), btScalar(rootAboveGroundHeight-0.5*gForeLegLength), btScalar(footYUnitPosition*(gRootBodyRadius+gLegLength)))); transform.setOrigin(btVector3(btScalar(footXUnitPosition*(gRootBodyRadius+gLegLength)), btScalar(rootAboveGroundHeight-0.5*gForeLegLength), btScalar(footYUnitPosition*(gRootBodyRadius+gLegLength))));
m_bodies[2+2*i] = localCreateRigidBody(btScalar(1.), bodyOffset*transform, m_shapes[2+2*i]); m_bodies[2+2*i] = localCreateRigidBody(btScalar(1.), bodyOffset*transform, m_shapes[2+2*i]);
m_bodies[2+2*i]->setUserPointer(this);
// m_bodyTouchSensorIndexMap.insert(std::pair<void*,int>(m_bodies[2+2*i],2+2*i));
// Setup the constraints
//
// hip joints // hip joints
localA.setIdentity(); localB.setIdentity(); localA.setIdentity(); localB.setIdentity();
@@ -224,7 +257,6 @@ public:
hingeC->setLimit(btScalar(-0.75 * SIMD_PI_4), btScalar(SIMD_PI_8)); hingeC->setLimit(btScalar(-0.75 * SIMD_PI_4), btScalar(SIMD_PI_8));
//hingeC->setLimit(btScalar(-0.1), btScalar(0.1)); //hingeC->setLimit(btScalar(-0.1), btScalar(0.1));
m_joints[2*i] = hingeC; m_joints[2*i] = hingeC;
m_ownerWorld->addConstraint(m_joints[2*i], true);
// knee joints // knee joints
localA.setIdentity(); localB.setIdentity(); localC.setIdentity(); localA.setIdentity(); localB.setIdentity(); localC.setIdentity();
@@ -235,7 +267,25 @@ public:
//hingeC->setLimit(btScalar(-0.01), btScalar(0.01)); //hingeC->setLimit(btScalar(-0.01), btScalar(0.01));
hingeC->setLimit(btScalar(-SIMD_PI_8), btScalar(0.2)); hingeC->setLimit(btScalar(-SIMD_PI_8), btScalar(0.2));
m_joints[1+2*i] = hingeC; m_joints[1+2*i] = hingeC;
m_ownerWorld->addConstraint(m_joints[1+2*i], true);
m_ownerWorld->addRigidBody(m_bodies[1+2*i]); // add thigh bone
m_ownerWorld->addConstraint(m_joints[2*i], true); // connect thigh bone with root
if(nn3DWalkers->detectCollisions()){ // if thigh bone causes collision, remove it again
m_ownerWorld->removeRigidBody(m_bodies[1+2*i]);
m_ownerWorld->removeConstraint(m_joints[2*i]); // disconnect thigh bone from root
}
else{
m_ownerWorld->addRigidBody(m_bodies[2+2*i]); // add shin bone
m_ownerWorld->addConstraint(m_joints[1+2*i], true); // connect shin bone with thig
if(nn3DWalkers->detectCollisions()){ // if shin bone causes collision, remove it again
m_ownerWorld->removeRigidBody(m_bodies[2+2*i]);
m_ownerWorld->removeConstraint(m_joints[1+2*i]); // disconnect shin bone from thigh
}
}
} }
// Setup some damping on the m_bodies // Setup some damping on the m_bodies
@@ -245,9 +295,6 @@ public:
m_bodies[i]->setDeactivationTime(0.8); m_bodies[i]->setDeactivationTime(0.8);
//m_bodies[i]->setSleepingThresholds(1.6, 2.5); //m_bodies[i]->setSleepingThresholds(1.6, 2.5);
m_bodies[i]->setSleepingThresholds(0.5f, 0.5f); m_bodies[i]->setSleepingThresholds(0.5f, 0.5f);
m_bodies[i]->setUserPointer(this);
m_bodyTouchSensorIndexMap.insert(std::pair<void*,int>(m_bodies[i],i));
} }
} }
@@ -297,9 +344,10 @@ public:
void legMotorPreTickCallback (btDynamicsWorld *world, btScalar timeStep) void legMotorPreTickCallback (btDynamicsWorld *world, btScalar timeStep)
{ {
NN3DWalkers* motorDemo = (NN3DWalkers*)world->getWorldUserInfo(); NN3DWalkersExample* motorDemo = (NN3DWalkersExample*)world->getWorldUserInfo();
motorDemo->setMotorTargets(timeStep); motorDemo->setMotorTargets(timeStep);
nn3DWalkers->detectCollisions();
} }
@@ -315,8 +363,9 @@ bool legContactProcessedCallback(btManifoldPoint& cp,
if (ID2 != GROUND_ID || ID1 != GROUND_ID) { if (ID2 != GROUND_ID || ID1 != GROUND_ID) {
// Make a circle with a 0.9 radius at (0,0,0) // Make a circle with a 0.9 radius at (0,0,0)
// with RGB color (1,0,0). // with RGB color (1,0,0).
if(nn3DWalkers->m_dynamicsWorld->getDebugDrawer() != NULL) if(nn3DWalkers->m_dynamicsWorld->getDebugDrawer() != NULL){
nn3DWalkers->m_dynamicsWorld->getDebugDrawer()->drawSphere(cp.getPositionWorldOnA(), 0.1, btVector3(1., 0., 0.)); nn3DWalkers->m_dynamicsWorld->getDebugDrawer()->drawSphere(cp.getPositionWorldOnA(), 0.1, btVector3(1., 0., 0.));
}
if(ID1 != GROUND_ID){ if(ID1 != GROUND_ID){
((NNWalker*)ID1)->setTouchSensor(o1); ((NNWalker*)ID1)->setTouchSensor(o1);
@@ -331,7 +380,7 @@ bool legContactProcessedCallback(btManifoldPoint& cp,
void NN3DWalkers::initPhysics() void NN3DWalkersExample::initPhysics()
{ {
gContactProcessedCallback = legContactProcessedCallback; gContactProcessedCallback = legContactProcessedCallback;
@@ -408,22 +457,22 @@ void NN3DWalkers::initPhysics()
} }
{ // create a slider to change the fore leg radius { // create a slider to change the fore leg radius
SliderParams slider("Fore Leg radius", &gForeLegRadius); SliderParams slider("Fore Leg radius", &gForeLegRadius);
slider.m_minVal = 0.01f; slider.m_minVal = 0.01f;
slider.m_maxVal = 10; slider.m_maxVal = 10;
slider.m_clampToNotches = false; slider.m_clampToNotches = false;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter( m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider); slider);
} }
{ // create a slider to change the fore leg length { // create a slider to change the fore leg length
SliderParams slider("Fore Leg length", &gForeLegLength); SliderParams slider("Fore Leg length", &gForeLegLength);
slider.m_minVal = 0.01f; slider.m_minVal = 0.01f;
slider.m_maxVal = 10; slider.m_maxVal = 10;
slider.m_clampToNotches = false; slider.m_clampToNotches = false;
m_guiHelper->getParameterInterface()->registerSliderFloatParameter( m_guiHelper->getParameterInterface()->registerSliderFloatParameter(
slider); slider);
} }
// Setup a big ground box // Setup a big ground box
@@ -464,13 +513,13 @@ void NN3DWalkers::initPhysics()
} }
void NN3DWalkers::spawnWalker(const btVector3& startOffset, bool bFixed) void NN3DWalkersExample::spawnWalker(const btVector3& startOffset, bool bFixed)
{ {
NNWalker* walker = new NNWalker(m_dynamicsWorld, startOffset, bFixed); NNWalker* walker = new NNWalker(m_dynamicsWorld, startOffset, bFixed);
m_walkers.push_back(walker); m_walkers.push_back(walker);
} }
void NN3DWalkers::setMotorTargets(btScalar deltaTime) void NN3DWalkersExample::setMotorTargets(btScalar deltaTime)
{ {
float ms = deltaTime*1000000.; float ms = deltaTime*1000000.;
@@ -521,7 +570,7 @@ void NN3DWalkers::setMotorTargets(btScalar deltaTime)
} }
} }
bool NN3DWalkers::keyboardCallback(int key, int state) bool NN3DWalkersExample::keyboardCallback(int key, int state)
{ {
switch (key) switch (key)
{ {
@@ -542,7 +591,7 @@ bool NN3DWalkers::keyboardCallback(int key, int state)
void NN3DWalkers::exitPhysics() void NN3DWalkersExample::exitPhysics()
{ {
gContactProcessedCallback = NULL; // clear contact processed callback on exiting gContactProcessedCallback = NULL; // clear contact processed callback on exiting
@@ -558,7 +607,7 @@ void NN3DWalkers::exitPhysics()
CommonRigidBodyBase::exitPhysics(); CommonRigidBodyBase::exitPhysics();
} }
void NN3DWalkers::renderScene() void NN3DWalkersExample::renderScene()
{ {
m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld); m_guiHelper->syncPhysicsToGraphics(m_dynamicsWorld);
@@ -569,7 +618,7 @@ void NN3DWalkers::renderScene()
class CommonExampleInterface* ET_NN3DWalkersCreateFunc(struct CommonExampleOptions& options) class CommonExampleInterface* ET_NN3DWalkersCreateFunc(struct CommonExampleOptions& options)
{ {
nn3DWalkers = new NN3DWalkers(options.m_guiHelper); nn3DWalkers = new NN3DWalkersExample(options.m_guiHelper);
return nn3DWalkers; return nn3DWalkers;
} }