Squirrely dynamic bodies resting on flat static surface (video)

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Squirrely dynamic bodies resting on flat static surface (video)

I'm having some issues with squirrely dynamic bodies attempting to rest on a flat static body.

I have a static "ground plane," 40x40 units, that I've tried constructing a number of different ways:

- btBoxShape of varying thickness
- btConvexHullShape created from a plane geometry
- btBvhTriangleMeshShape created from a plane geometry with varying number of subdivisions.

In my test, I create a number of small dynamic bodies (.5 - 1.5 units on longest axis) using btConvexHullShape, reduced via btShapeHull, and drop them from the air onto the static ground body.

The simulation seems to act normally until it's time for the dynamic bodies to come to rest on the ground. They often do not lie flat on the surface and do strange things like spinning indefinitely on their corners. See gifs below.

I've done a lot of tweaking with friction, restitution, sleeping thresholds, damping, etc on the dynamic objects and on the static ground. Some combinations can somewhat mitigate the issues, but all have undesirable tradeoffs. The closest I've found to making things behave correctly is setting the mass of the dynamic objects to something very high (500+), but this too has undesirable side effects.

Mass == 2000:

What am I doing wrong?

Some other info:

The small grid marks on the ground are 1 unit increments
Timestep is 1.0/120.0 — have tried much smaller
Gravity is -9.8
Using btBoxShape instead of btConvexHullShape for the dynamic objects exhibits the same behavior, only to a lesser severity.

PcChip
Posts: 33
Joined: Sun May 20, 2018 3:09 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

try this:

ground:
restitution = 0.0
friction = 1.0

objects:
restitution = 0.3
friction = 0.5

make sure you don't have sleeping disabled for the objects (make sure you did not myRigidBody->setActivationState(DISABLE_DEACTIVATION); )

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Thanks chip.

Generally activiationState gets set to ACTIVE_TAG when the rigid body is created in my code -- I disabled it to leave it as Bullet's default, then changed the friction and restitution settings as you recommended. Here is the result:

Mwni
Posts: 9
Joined: Thu Jul 12, 2018 4:43 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

I had the same problem with cylinders that were inexplicably rolling around once on the floor.
Have you tried increasing the solver iteration count to something higher than the default of 10?

Code: Select all

``world->getSolverInfo()->m_numIterations = 30``

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Hi Mwni,

I played around with m_numIterations a bit. Setting to 0 results in no dynamic<->static interaction as expected, but anything larger seems to have no effect.

m_numIterations = 0:

m_numIterations = 10:

m_numIterations = 100:

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Another example using boxes. The spinning phenomenon is a lot less common, but boxes often don't lay flat on the ground. btBoxShape, mass=1

PcChip
Posts: 33
Joined: Sun May 20, 2018 3:09 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

I have an "opengl / bullet physics playground" project in visual studio that I try new things in, so the code is very hacky and ugly, but this is what works normally for me:

Code: Select all

``````	// Build the broadphase
// Set up the collision configuration and dispatcher
btDefaultCollisionConfiguration* collisionConfiguration = new btDefaultCollisionConfiguration();
btCollisionDispatcher* dispatcher = new btCollisionDispatcher(collisionConfiguration);

// The actual physics solver
btSequentialImpulseConstraintSolver* solver = new btSequentialImpulseConstraintSolver;

// The world.
dynamicsWorld = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
dynamicsWorld->setGravity(btVector3(0, -9.8, 0));

PhysicsDebugDraw* m_debugDraw = new PhysicsDebugDraw();
dynamicsWorld->setDebugDrawer(m_debugDraw);

btContactSolverInfo& info = dynamicsWorld->getSolverInfo();
info.m_numIterations = 4;
``````

Code: Select all

``````	for (int i = 0; i < 20; i++)
{

btScalar mass = 1;
btVector3 fallInertia((rand() % 4)-1, (rand() % 3)-2, (rand() % 6)-3);
fallShape->calculateLocalInertia(mass, fallInertia);
fallMotionStates.emplace_back(new btDefaultMotionState(btTransform(btQuaternion(rand()%3, rand() % 3, rand() % 3, 1), btVector3(rand()%20+2, rand() % 5 + 10, rand() % 20+2))));
btRigidBody::btRigidBodyConstructionInfo fallRigidBodyCI(mass, fallMotionStates[i], fallShape, fallInertia);
fallRigidBodyCI.m_restitution = 0.2;
fallRigidBodyCI.m_friction = 1;
fallingRigidBodies.emplace_back(new btRigidBody(fallRigidBodyCI));
fallingRigidBodies[i]->setUserPointer((void*)i);
//fallingRigidBodies[i]->setCcdMotionThreshold(0.1);
}
``````

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Chip, my code appears to do essentially all the same things as yours, except that I calculate localInertia like this:

btVector3 localInertia = {0, 0, 0}
collisionShape->calculateLocalInertia(mass, localInertia);

Note sure if that's correct...

If I try it with your random method of calculating localInertia, I get boxes that lay nice and flat, but don't rotate, and fruit that never loses the small amount of angular velocity I assign to it when it first enters the world.

Mwni
Posts: 9
Joined: Thu Jul 12, 2018 4:43 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

Now, this is really strange. Box shapes atleast have always worked very well for me...

The last guess I could make is to increase the substeps for the simulation steps.

Code: Select all

``world->stepSimulation(1/60, 5, 1/300)``
This for example subdivides 60 Hz steps into 5 substeps. I found this has drastically improved the stability of constraints. Drawback is that it most likely increases performance cost alot.

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Hi Mwni,

Unfortunately timestep & number of substeps don't appear to be the issue.

Since the simulation appears to run much more stably with very high masses (10,000x scale) I'm tempted to just move forward with that.

I'm wondering what types unforeseen issues scaling the mass for all my objects may present in the future. Obviously applied forces and torques need to be adjusted. Perhaps restitution will need tweaking as well. What adjustments might need to be made?

PcChip
Posts: 33
Joined: Sun May 20, 2018 3:09 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

this is how I call stepSimulation (in both my hacky playground project, and my actual hobby game project)

Code: Select all

``````
simTime = glfwGetTime();
dynamicsWorld->stepSimulation(deltaTime, 20, 1./100);
dynamicsWorld->synchronizeMotionStates();  //if I remember correctly this was for the btRaycastVehicle's wheels
if (drawDebug)
{
dynamicsWorld->debugDrawWorld();
}
simTime = (glfwGetTime() - simTime);
``````

I would suggest starting a new project, compiling a fresh version of Bullet from github, and testing there with a basic bare-bones approach

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Everything with configuring the world, creating shapes and rigid bodies, and configuring those objects all seems to be by the book...

There are only two things that I am somewhat concerned about:

1. For resource management and scene graph synchronization purposes, I'm storing bt objects (btRigiBody, bt...Shape, etc) in std::maps, which map them to their associated higher-level game objects/nodes. I am not making any use of btAlignedObjectArray. It's my understanding that this is okay as long as I don't use SSE (I'm not -- I was getting crashes every once in a while in a Bullet SSE-enabled function when converting OpenGL matrices to BT matrices and vise-versa. Commenting out the SSE code to enable the regular user code seemed to fix the issue.)

2. I can't say why, but my simulation stepping seems a little smelly. It essentially looks like this:

btWorld->stepSimulation(deltaSeconds, 10, 1.0/120.0);

My test (gifs posted above) is running somewhere in the neighborhood of 300-400fps, so deltaSeconds is between 0.0025 and 0.0033 for any given step.

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Thanks Chip. Probably a good idea.

I think I will try managing the physics simulation from the "client side" of my framework (as opposed to opaquely through a wrapper) first, then start from scratch. Weird stuff.
Last edited by goosesensor on Sat Jul 21, 2018 2:42 am, edited 1 time in total.

PcChip
Posts: 33
Joined: Sun May 20, 2018 3:09 pm

Re: Squirrely dynamic bodies resting on flat static surface (video)

regarding bullet to opengl, I stole this from a forum somewhere

Code: Select all

``````glm::mat4 bulletToGlm(const btTransform& t)
{
glm::mat4 m(0);
const btMatrix3x3& basis = t.getBasis();
// rotation
for (int r = 0; r < 3; r++)
{
for (int c = 0; c < 3; c++)
{
m[c][r] = basis[r][c];
}
}
// traslation
btVector3 origin = t.getOrigin();
m[3][0] = origin.getX();
m[3][1] = origin.getY();
m[3][2] = origin.getZ();
// unit scale
m[0][3] = 0.0f;
m[1][3] = 0.0f;
m[2][3] = 0.0f;
m[3][3] = 1.0f;
return m;
}``````

goosesensor
Posts: 11
Joined: Tue Jul 17, 2018 3:50 am
Location: Santa Cruz, CA

Re: Squirrely dynamic bodies resting on flat static surface (video)

Thanks... plugged that in to replace my existing function:

mat4 GLMMat4FromBTTransform(const btTransform& from) {
mat4 glmMat;
from.getOpenGLMatrix(value_ptr(glmMat));
return glmMat;
}

Exacto-el-same-o.