Kinematic objects colliding with dynamic objects very badly

Post Reply
ed_welch
Posts: 43
Joined: Wed Mar 04, 2015 6:16 pm

Kinematic objects colliding with dynamic objects very badly

Post by ed_welch »

Kinematic objects do not seem to interact very well with dynamic objects. When you call m_pRigidBody->getWorldTransform().setOrigin() it caterpults any dynamic objects in it's way with enormous force. Is this normal?
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Kinematic objects colliding with dynamic objects very badly

Post by drleviathan »

What you want to do is to also set the velocities of the kinematic object correctly. Setting the velocities doesn't help move it to new transoforms, but it does help the collision system impart correct velocity on the dynamic object, allowing it to be knocked out of the way instead of getting into a state of interpenetration and then being ejected by non-physical algorithms.

So, you need to measure the velocity and ideally this would be done once per substep, which means you would give your Kinematic object a custom KinematicMotionsState and put the velocity measuring logic inside KinematicMotionState::getWorldTransform() method. It might look something like this:

Code: Select all

///synchronizes world transform from user to physics
void KinematicMotionState::getWorldTransform(btTransform & newWorldTransform) const override {
    // linear velocity
    btVector3 old_position = m_body->getWorldTransform().getPosition();
    btVector3 new_position = newWorldTransform.getOrigin();                              
    btVector3 new_linear_velocity = (new_position - old_position) / SUBSTEP_DURATION;
    constexpr btScalar MIN_LINEAR_SPEED_SQUARED = 0.0001;     // 1 cm/sec
    if (new_linear_velocity.length2() < MIN_LINEAR_SPEED_SQUARED) {
        new_linear_velocity.setZero();
    }
    m_body->setLinearVelocity(new_linear_velocity);
    
    // angular velocity
    btQuaternion old_rotation = m_body->getWorldTransform().getRotation();
    btQuaternion new_rotation = newWorldTransform.getRotation();
    btQuaternion delta_rotation = m_body->getWorldTransform().getRotation().inverse() * newWorldTransform.getRotation();
    btScalar delta_angle = delta_rotation.getAngle();
    btVector3 new_angular_velocity(0.0, 0.0, 0.0);  
    constexpr btScalar MIN_ANGULAR_SPEED = 0.01; // radians/sec
    if (angle > MIN_ANGULAR_SPEED) {
        new_angular_velocity = (angle / SUBSTEP_DURATION) * delta_rotation.getAxis();
    }
    m_body->setAngularVelocity(new_angular_velocity);
    
    // transform
    m_body->setWorldTransform(newWorldTransform);
}
Note: that is written from scratch and I didn't bother to compile it, so it may have bugs and typos. Tune the constants to suit your application.
ed_welch
Posts: 43
Joined: Wed Mar 04, 2015 6:16 pm

Re: Kinematic objects colliding with dynamic objects very badly

Post by ed_welch »

Thanks for the reply. Unfortunately, it makes no difference. I think velocity is ignored for kinematic objects.

Edit:
I finally figured it out. I was directly updating the WorldTransform, without updating the MotionState. I changed this to update both and now it works great:

Code: Select all

		btTransform& t = m_pRigidBody->getWorldTransform();
		t.setOrigin(btVector3(m_x+m_xOffset, m_y+m_yOffset, m_z));
		m_pRigidBody->getMotionState()->setWorldTransform(t);	// adding this line fixed the problem
Post Reply