I require suspension modelling, for which I need extreme mass ratios(small wheels vs a massive airplane). The way I approached this issue was by lowering the time step size to 1/1000th, however now that I started toying around with terrain, I discovered that my plane, currently consisting of two suspended wheels and a box with the box resting on the ground by one edge, would jump considerably, seemingly at random at said edge it is resting on. This is less pronounced at higher timestep lengths, however that breaks the suspension and does not completly eliminate the bouncing.
In my search for a solution I came across a thread which seems to be about a related issue. It having to do with edge contacts makes sense to me, as pushing the aircraft in one direction on the plane, results in a regular pattern of bumps, although it does not always jump that high.
The OP of that thread solved it by implementing a custom callback, however that seems to do nothing for my issue at hand, the behavior seems to exactly identical despite the callback being called(which I could confirm via a console print).
Here is a shortened version of my implementation. I hope I am not omitting crucial information here. My biggest worry there is that I could have implemented something like the generation of the triangleInfoMap wrong, leading to no effect from the callback.
Code: Select all
bool collisionCallback(btManifoldPoint& cp, const btCollisionObjectWrapper* obj1, int id1, int index1, const btCollisionObjectWrapper* obj2, int id2, int index2)
{
btAdjustInternalEdgeContacts(cp, obj2, obj1, id2, index2);
return true;
}
void main()
{
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);
btBroadphaseInterface* overlappingPairCache = new btDbvtBroadphase();
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;
btDiscreteDynamicsWorld* dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
double testheight[100 * 100];
for (int i = 0; i < 100 * 100; i++)
{
testheight[i] = 0.0f;
}
gContactAddedCallback = collisionCallback;
btHeightfieldTerrainShape* terrainshape = new btHeightfieldTerrainShape(100, 100, &testheight, btScalar(10), 1, true, true);
btTriangleInfoMap* triangleInfoMap = new btTriangleInfoMap();
btGenerateInternalEdgeInfo(terrainshape, triangleInfoMap);
terrainshape->setTriangleInfoMap(triangleInfoMap);
btCollisionShape* groundShape = terrainshape;
btTransform groundTransform;
groundTransform.setIdentity();
groundTransform.setOrigin(btVector3(0, 3, 0));
btScalar mass(0.);
btVector3 localInertia(0, 0, 0);
if (mass != 0.f)
groundShape->calculateLocalInertia(mass, localInertia);
btDefaultMotionState* myMotionState = new btDefaultMotionState(groundTransform);
btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, terrainshape, localInertia);
btRigidBody* body = new btRigidBody(rbInfo);
body->setCollisionFlags(body->getCollisionFlags() | btCollisionObject::CF_CUSTOM_MATERIAL_CALLBACK);
dynamicsWorld->addRigidBody(body);
while(!glfwWindowShouldClose(window))
{
dynamicsWorld->stepSimulation(deltaTime, 100, 0.001);
}
}