Page 1 of 1

Object falls a third of its height through the ground

Posted: Sat Aug 28, 2021 4:27 pm
by justjayel
Hiya,

I have set up a very simple demo using Bullet where an object moves along the ground using linear velocity which is constantly set to the same value over 200 frames and then the object falls through the ground but only up to a third of its height. E.g.: If I have a RidgidBody with a box collision of size x: 2, y: 8, z: 2 (half extents x: 1, y: 4, z: 1) after 200 or so frames the object falls from position 4 to 1 (ground's top is at zero).


I have set it up with the following:
  • Time step and fixed time step set to 0.0167f (so 60hz)
  • Added a ground with box collision, zero mass.
  • The dynamic object has a box collision.
I also get a similar issue when a dynamic object is falling with the collision half extents of x: 0.2, y: 1, z: 0.2

Any ideas why this is happening?


My code is all wrapped up with custom code, so I have pulled out all the Bullet Physics specific code and placed it below:

Code: Select all

float timeStep = 0.0167f;
btDiscreteDynamicsWorld* dynamicsWorld = // Standard set up of btDiscreteDynamicsWorld
dynamicsWorld->setGravity(btVector3(0, -5, 0));
dynamicsWorld->getSimulationIslandManager()->setSplitIslands(false);
{
	btCollisionShape* groundShape = new btBoxShape(btVector3(40, 5, 40));
	btVector3 localInertia(0, 0, 0);
	
	btTransform initialTransform;
	initialTransform.setIdentity();
	initialTransform.setOrigin(btVector3(0, -5, 0));
	
	btDefaultMotionState* myMotionState = new btDefaultMotionState(initialTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(0, myMotionState, groundShape, localInertia);
	
	btRigidBody* rb = new btRigidBody(rbInfo);
	rb->setActivationState(DISABLE_DEACTIVATION);
	rb->setSleepingThresholds(0,0);
	dynamicsWorld->addRigidBody(rb, 1, 1);
}

{
	float mass = 1;
	btCollisionShape* playerShape = new btBoxShape(btVector3(1, 4, 1));
	btVector3 localInertia(0, 0, 0);
	playerShape ->calculateLocalInertia(mass, localInertia);
	
	btTransform initialTransform;
	initialTransform.setIdentity();
	initialTransform.setOrigin(btVector3(0, 4, 0));
	
	btDefaultMotionState* myMotionState = new btDefaultMotionState(initialTransform);
	btRigidBody::btRigidBodyConstructionInfo rbInfo(mass, myMotionState, playerShape, localInertia);
	
	btRigidBody* rb = new btRigidBody(rbInfo);
	rb->setActivationState(DISABLE_DEACTIVATION);
	rb->setSleepingThresholds(0,0);
	dynamicsWorld->addRigidBody(rb, 1, 1);
}

for (int i = 0; i < 1000; i++)
{
	dynamicsWorld->stepSimulation(timeStep , 10, timeStep);
	
	btRigidBody* playerRb = //get the player object. 
	
	// Simulate a constant velocity
	if(i > 50 && i < 200)
	{
		btVector3 newVelocity = btVector3(2.0f, 0, 0);
		playerRb->setLinearVelocity(newVelocity);
	}
}

Re: Object falls a third of its height through the ground

Posted: Sun Aug 29, 2021 10:32 am
by ed_welch
Try setting a small amount of margin on both objects:
pCollisionShape->setMargin(0.05f);

Re: Object falls a third of its height through the ground

Posted: Sun Aug 29, 2021 12:11 pm
by justjayel
I've tried setting the margin (at 0.05f and higher) after creating the collision shape and before adding it into the btDiscreteDynamicsWorld and it doesn't work.

Code: Select all

btCollisionShape* colliderShape = new btBoxShape(btVector3(inputs[0], inputs[1], inputs[2]));
colliderShape->setMargin(0.5f);

btRigidBody* rb = // create the rigid body
dynamicsWorld->addRigidBody(rb, 1, 1);

For the main issue it doesn't occur if I am setting the linear velocity constantly for less than 60 frames. But I don't think that a viable workaround.

Code: Select all

if(i > 50 && i < 110)
{
	btVector3 newVelocity = btVector3(2.0f, 0, 0);
	playerRb->setLinearVelocity(newVelocity);
}

Re: Object falls a third of its height through the ground

Posted: Sun Aug 29, 2021 3:59 pm
by drleviathan
Slamming the linear velocity of a dynamic object to an arbitrary value is a Bad Idea in general because it could override velocities from collisions that would otherwise help resolve interpenetration.

One way to avoid breaking the simulation is to use applyForce() instead of setLinearVelocity() because the force will be accumulated until the substep and then introduced during the constraint solver step, which allows collisions to negate forces that would violate their constraint parameters. However forces are difficult to tune and compute for obtaining the effect you want which is why I usually do it a different way.

Blend toward the target_velocity every substep like so:

Code: Select all

// blend_timescale is the exponential timescale time it takes for the object to change its velocity
// toward the target.  After one period the object will decrease the delta to 1/e of what it was.
// The shorter the timescale the faster it adjusts, for very long timescales the
// object takes forever to respond.  It cannot be shorter than the substep_period (else instability).
// For best results it should be not less than two or three substep_periods, but typically for human
// interaction timescales you can allow the period to be something closer to half a second.
// This is your easy one-knob tuning adjustment to make the object's responsiveness just right.
btScalar blend_timescale = 2.0; // seconds

// blend
btScalar del = substep_period / blend_timescale;
btVector3 new_velocity = (1.0 - del) * current_velocity + del * target_velocity;

// slam
body->setLinearVelocity(new_velocity);
If you set the blend_timescale to a reasonable value then you give the collision constraints time to successfully push the object out of penetration.

Note, this method is mass agnostic.

Re: Object falls a third of its height through the ground

Posted: Sun Aug 29, 2021 11:47 pm
by justjayel
Hi drleviathan,
Can substep_period and blend_timescale be any static values within your description? I'll try this a bit later when I have more time.


I quickly checked my issue again on the HelloWorld demo and it seems like the issue is somewhat related to the ratio of the collision shape; seems like tall slim objects will fall through the ground and stay there. Ratios less than a 0.3 between X and Y seems to run into this issue. E.g.:
  • X: 1, Y: 4 - fails
  • X: 1.2, Y: 4 - works

Re: Object falls a third of its height through the ground

Posted: Mon Aug 30, 2021 2:54 pm
by drleviathan
For stability your substep_period should be fixed. I believe the default behavior in Bullet is fixed step_period = 1/60 sec with 1 substep per step.

Yes, for most applications the blend_timescale would be a constant. You would tweak it to get the responsiveness you want and then nail it down as a compile time constant.

I wonder if the X/Y ratio threshold is actually caused by the tall box starting to tip over because of friction at the contacts. For curiosity's sake maybe try setting all frictions (floor and dynamic object) to be zero to see if the the transition between behaviors goes away.

Re: Object falls a third of its height through the ground

Posted: Wed Sep 01, 2021 2:38 pm
by justjayel
Hi drleviathan,

Seems you were right, the setFriction() method worked! Stops my character object from sinking. Thanks!!

The gradual incremental velocity I don't think helped, but its great for simulating a bit of realism, I will definitely look into using it!

Thanks again!

Re: Object falls a third of its height through the ground

Posted: Wed Sep 01, 2021 3:06 pm
by drleviathan
If you're trying to make a tall think character always stand up maybe you should use the "zero inverse inertia tensor diagonal" trick. This would allow you to use whatever friction you want. In other words, if your character should only ever rotate about its local vertical Y-axis, then you can set the X- and Z-components of its local inverse inertia tensor diagonal to zero like so:

Code: Select all

btVector3 inv_inertia = body->getInvInertiaDiagLocal();
inv_inertia.setX(0.0f);
inv_inertia.setZ(0.0f);
body->setInvInertiaDiagLocal(inv_inertia);
Effectively this is like setting its local angular mass to infinity on those two axes --> torques will never be able to budge it except around its one pivot axis.

Re: Object falls a third of its height through the ground

Posted: Sat Sep 11, 2021 3:20 pm
by justjayel
drleviathan wrote: Wed Sep 01, 2021 3:06 pm If you're trying to make a tall think character always stand up maybe you should use the "zero inverse inertia tensor diagonal" trick. This would allow you to use whatever friction you want. In other words, if your character should only ever rotate about its local vertical Y-axis, then you can set the X- and Z-components of its local inverse inertia tensor diagonal to zero like so:

Code: Select all

btVector3 inv_inertia = body->getInvInertiaDiagLocal();
inv_inertia.setX(0.0f);
inv_inertia.setZ(0.0f);
body->setInvInertiaDiagLocal(inv_inertia);
Effectively this is like setting its local angular mass to infinity on those two axes --> torques will never be able to budge it except around its one pivot axis.
Your solution worked.

Now if I set the friction on both objects to non-zero and apply a little velocity to the player in either X or Z direction it spins slowly in a circle around the Y axis. Would anyone know why?

On a different note, is there anywhere with a bit more in depth tutorials or documentation? Is it just the examples?


EDIT:
I fixed the spinning by setting the inverse inertia on the Y axis to zero as well. Not sure if that is the correct way. But I guess that is fine for a character rather than an actual object?

Code: Select all

inv_inertia.setY(0.0f);

Re: Object falls a third of its height through the ground

Posted: Sat Sep 11, 2021 6:34 pm
by drleviathan
Setting the inverse inertia diagonal to zeros is fine: it produces an object that will never ever rotate from external forces, which is often what you want for a character. With dynamic characters I typically push them around with velocity adjustments, allow them to rotate about the vertical axis, but slam their rotation and zero their angular velocity every step, which is effectively the same thing. Another way to put it is: my characters are dynamic in the linear dimensions but kinematic in the angular.

Re: Object falls a third of its height through the ground

Posted: Tue Feb 14, 2023 8:23 am
by lorde
I am also interested in this!
melon playground

Re: Object falls a third of its height through the ground

Posted: Tue Jun 20, 2023 6:44 am
by sharase23
Regarding the X/Y ratio threshold, it's possible that the tall box's tipping behavior is influenced by friction at the contacts. To investigate this, you can try setting the friction values to zero for both the floor and the dynamic object. This can help determine if the transition between behaviors is affected by friction and provide further insights into the simulation.
fnf