So, I'm encountering something which (to me) seems confusing and undesirable. When I have a kinetic rigid body in a world with gravity, gravity will only affect the rigid body and pull it down while the rigid body's activation state is active. Furthermore, after activating the activation state, even though the rigid body is being moved through gravity, the rigid body will deactivate; therefore, my only solution thus far to make sure that rigid bodies are always affected by gravity, I've been forced to use DISABLE_DEACTIVATION as an activation state. But this doesn't seem desirable at all, because there would be no gain from using activation states if we're merely suppose to disable it entirely.
Is there a way to allow a rigid body to be affected by gravity without being active? Or to allow the rigid body to at least not deactivate until the effects of gravity are counteracted by a ground (the gravity stops moving the rigid body)?
Gravity and deactivation
-
- Posts: 13
- Joined: Fri Apr 05, 2013 6:19 am
- Location: Pittsburgh, PA
-
- Posts: 13
- Joined: Fri Apr 05, 2013 6:19 am
- Location: Pittsburgh, PA
Re: Gravity and deactivation
I think I figured out my problem; I have too low of a linear threshold, and so while my btRigidBody is moving, it is actually "non-moving." Because I found so little documentation on activation states and the like, I'm posting the "wealth" of my knowledge of the subject here, so that hopefully someone else can learn (or, if I'm mistaken in my understanding, that someone can correct me).
------------
btCollisionObjects have what is known as an activation state. This state is an optimization in regards to how Bullet manages the world; if whatever physics world model you're using has 10,000 collision objects, then each time you step the simulation, you would need to perform collision checks an inordinate number of times (something like 99,990,000 collision tests). Even if those checks were lightning fast, that's still almost 100,000,000 checks each frame of your application (if you step the simulation at each frame, as is commonly done).
So Bullet made a logical conclusion — only test for collisions involving a pair of objects where at least one object has moved since we last checked. For instance, we have 10,000 objects, but let's say that only one object has actually moved, and other other 9,999 objects remained stationary. If these 9,999 objects that didn't move weren't colliding before, and they haven't moved since the last time we checked, how would they be colliding now (unless we as programmers made them to, but that's another issue). So instead of checking 99,990,000 collision pairs (10,000 objects * 9,999 potential other objects to collide with), Bullet only has to check 9,999 collision pairs (the one object that moved * 9,999 other objects that this object could have collided with).
Bullet is designed so that we manually tell it when an object is about to move. In order for Bullet to do any concerning a btCollisionObject, that btCollisionObject must be in an active activation state. If it is active, then velocity will be applied, collision will be checked, and so on. If the btCollisionObject is in a deactivated activation state, then it will be considered stationary; velocity won't be applied, collision will be skipped for this object (not that other objects can't collide with this object; just that this object can't collide with other objects).
However objects that are active but haven't moved will be deactivated; if everything remained in its active state forever, there would be very little gain from having activation states at all (it would only exclude objects which have never moved before). This process happens automatically, after a period of time known as the deactivation time has elapsed. But this deactivation time might not suit your individual needs; therefore, there's one of two ways to work with it:
-----------------
Hopefully someone will find this helpful, and will have less of a scavenger hunt to figure out the ins and outs of beginning to work with activation states.
------------
btCollisionObjects have what is known as an activation state. This state is an optimization in regards to how Bullet manages the world; if whatever physics world model you're using has 10,000 collision objects, then each time you step the simulation, you would need to perform collision checks an inordinate number of times (something like 99,990,000 collision tests). Even if those checks were lightning fast, that's still almost 100,000,000 checks each frame of your application (if you step the simulation at each frame, as is commonly done).
So Bullet made a logical conclusion — only test for collisions involving a pair of objects where at least one object has moved since we last checked. For instance, we have 10,000 objects, but let's say that only one object has actually moved, and other other 9,999 objects remained stationary. If these 9,999 objects that didn't move weren't colliding before, and they haven't moved since the last time we checked, how would they be colliding now (unless we as programmers made them to, but that's another issue). So instead of checking 99,990,000 collision pairs (10,000 objects * 9,999 potential other objects to collide with), Bullet only has to check 9,999 collision pairs (the one object that moved * 9,999 other objects that this object could have collided with).
Bullet is designed so that we manually tell it when an object is about to move. In order for Bullet to do any concerning a btCollisionObject, that btCollisionObject must be in an active activation state. If it is active, then velocity will be applied, collision will be checked, and so on. If the btCollisionObject is in a deactivated activation state, then it will be considered stationary; velocity won't be applied, collision will be skipped for this object (not that other objects can't collide with this object; just that this object can't collide with other objects).
However objects that are active but haven't moved will be deactivated; if everything remained in its active state forever, there would be very little gain from having activation states at all (it would only exclude objects which have never moved before). This process happens automatically, after a period of time known as the deactivation time has elapsed. But this deactivation time might not suit your individual needs; therefore, there's one of two ways to work with it:
- btCollisionObject::setActivationState(DISABLE_DEACTIVATION); This forces the collision object to never deactivate. This function will activate the collision object, and until you otherwise specify, the collision object will remain active.
- btCollisionObject::setDeactivationTime(btScalar); Providing a btScalar to this function will set the new deactivation time for this collision object.
- Thresholds to compare magnitude of the velocity against
- Thresholds that, should all three components of the velocity (X, Y, and Z) fall beneath, the velocity will be considered (0, 0, 0)
Code: Select all
btRigidBody rigidBody;
rigidBody.setSleepingThreasholds(10.0, rigidBody.getAngularSleepingThreshold());
Hopefully someone will find this helpful, and will have less of a scavenger hunt to figure out the ins and outs of beginning to work with activation states.
-
- Posts: 13
- Joined: Fri Apr 05, 2013 6:19 am
- Location: Pittsburgh, PA
Re: Gravity and deactivation
Regarding how the thresholds are used when determining of a velocity constitutes "moving" or "non-moving," I tracked it down in the source, and it's the first of the two possibilities that I suggested. In terms of linear threshold, a btRigidBody is considered "non-moving" if the square of the linear threshold is greater than (but not equal to) the square of the length of the linear velocity. In the code, it is:
Code: Select all
if ((getLinearVelocity().length2() < m_linearSleepingThreshold*m_linearSleepingThreshold) &&
(getAngularVelocity().length2() < m_angularSleepingThreshold*m_angularSleepingThreshold))
{
// "non-moving"
} else
{
// "moving"
}