reactphysics3d icon indicating copy to clipboard operation
reactphysics3d copied to clipboard

`setTransform` without adding velocity.

Open twixuss opened this issue 3 years ago • 2 comments

I'm making a game with a big terrain. If I use absolute position for colliders, everything is fine around the center of the world. But if the player goes far enough, there's not enough precision in float32 to simulate everyting properly. So I came up with dividing the world into chunks and use chunk-relative positioning. When a player moves into a different chunk, I shift all the rigidbodies accordingly by using setTransform. This way collision works fine everywhere, but a different problem appears. If a dynamic body is close to a static body when the player moves into a different chunk, it just gains an insane amount of velocity and flies out of the world. I looked at setTransform implementation and saw that it always changes linear velocity and thought that maybe velocity shouldn't be changed when moving between chunks. I added an optional parameter bool updateLinearVelocity to setTransform which defaults to true, so now it looks like this:

class RigidBody : public CollisionBody {
    virtual void setTransform(const Transform& transform, bool updateLinearVelocity = true) override;
    ...
}
void RigidBody::setTransform(const Transform& transform, bool updateLinearVelocity) {

    const Vector3 oldCenterOfMass = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity);

    // Compute the new center of mass in world-space coordinates
    const Vector3& centerOfMassLocal = mWorld.mRigidBodyComponents.getCenterOfMassLocal(mEntity);
    mWorld.mRigidBodyComponents.setCenterOfMassWorld(mEntity, transform * centerOfMassLocal);

    // Update the linear velocity of the center of mass
    if (updateLinearVelocity) {
        Vector3 linearVelocity = mWorld.mRigidBodyComponents.getLinearVelocity(mEntity);
        const Vector3& angularVelocity = mWorld.mRigidBodyComponents.getAngularVelocity(mEntity);
        const Vector3& centerOfMassWorld = mWorld.mRigidBodyComponents.getCenterOfMassWorld(mEntity);
        linearVelocity += angularVelocity.cross(centerOfMassWorld - oldCenterOfMass);
        mWorld.mRigidBodyComponents.setLinearVelocity(mEntity, linearVelocity);
    }

    CollisionBody::setTransform(transform);

    // Awake the body if it is sleeping
    setIsSleeping(false);
}

When player moves between chunks I call setTransform with false and it works fine without the issue.

twixuss avatar Jun 28 '22 05:06 twixuss

Thanks a lot for your feedback.

I don't know if that's an option for your but maybe you can try to compile the library to use double precision for floating values instead. In CMake, you need to enable the RP3D_DOUBLE_PRECISION_ENABLED variable.

DanielChappuis avatar Jun 28 '22 07:06 DanielChappuis

Have you been able to test it?

DanielChappuis avatar Jul 21 '22 19:07 DanielChappuis

I am closing this issue. Feel free to reopen it if you have any news.

DanielChappuis avatar Feb 13 '24 22:02 DanielChappuis