M Zeinstra
M Zeinstra

Reputation: 1981

Bullet Physics - Angular factor doesn't apply

I'm currently using Bullet Physics to simulate physics in my world. Right now, I have a controllable player that can move with ApplyForce, but it does not have the ability to rotate, yet.

However, I lock the angular movement to the Y axis (pitch), but it doesn't seem to work:

At initialization:

// Player.cpp
m_physicsBodyComp->LockRotation({0.f, 1.f, 0.f});
// PhysicsBodyComponent.cpp
void tse::PhysicsBodyComponent::LockRotation(const TSVector3 & a_axis) {
    if(m_rigidBody)
        m_rigidBody->setAngularFactor(btVector3(a_axis.GetX(), a_axis.GetY(), a_axis.GetZ()));
}

Also, what might cause a problem too: Before the physics simulation I set the transform of the rigid body to the transform of my transform component, and after the physics simulation I set the transform of the transform component to the rigidbody transform.

// Before physics simulation
void tse::PhysicsBodyComponent::UpdateTransformComponent() {
    if(m_rigidBody) {
        if(m_transformComponent->m_wasDirty && m_transformComponent->IsValid()) {
            btQuaternion _quat;
            _quat.setEuler(m_transformComponent->m_rotation.GetY(), m_transformComponent->m_rotation.GetX(), m_transformComponent->m_rotation.GetZ());

            btTransform _trans;
            _trans.setRotation(_quat);
            _trans.setOrigin(m_transformComponent->m_position.GetVecBt());
            m_rigidBody->setWorldTransform(_trans);
            m_transformComponent->m_wasDirty = false;
            Activate();
        }
    }
}

// After physics simulation
void tse::PhysicsBodyComponent::Update(float a_deltaTime) {
    if(m_rigidBody) {
        if(m_bodyType == PhysicsBodyType::DYNAMIC) {
            btTransform & _trans = m_rigidBody->getWorldTransform();

            DirectX::XMVECTOR _rotation;
            btQuaternion _quat = _trans.getRotation();

            _rotation.m128_f32[0] = _quat.getX();
            _rotation.m128_f32[1] = _quat.getY();
            _rotation.m128_f32[2] = _quat.getZ();

            m_transformComponent->SetPosition(TSVector3(_trans.getOrigin()));
            m_transformComponent->SetRotation(_rotation);
        }
    }
}

So, the problem is that I lock the rotation of the x and z axis, but it still changes rotation of the x and z axis (a GIF of the problem is shown below). As I said earlier, I'm not rotation the player, yet. Every rotation that you see in the GIF below is purely done by Bullet Physics. I only move the player with AddForce.

Am I doing something completely wrong or is this a known bug in Bullet physics? Thanks in advance..!

'Rotation lock not working'

Upvotes: 0

Views: 1027

Answers (2)

The Diagnosed 9mm
The Diagnosed 9mm

Reputation: 39

I had the same issue, however if you call setAngularFactor() at every frame it should work

Upvotes: 0

OverFloo
OverFloo

Reputation: 23

Do you create a dynamic or kinematic rigidbody for your player?

Kinematic rigidbodies can only be moved/animated by the user, dynamic objects can also be moved through every other objects... See bullet user manual p. 19+20

So if your player should only be moved using addForce() etc., create a kinematic body.

How i create a kinematic rigidbody: (Example in C#, C++ should be similar)

// Create rigid Body
float mass = 0.0f; // kinematic bodies have no mass
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, new DefaultMotionState(), collisionShape);
RigidBody rigidBody = new RigidBody(rbInfo);
rbInfo.Dispose();

// Mass=0 -> static/kinematic possible -> use flag distinguish
rigidBody.CollisionFlags = CollisionFlags.KinematicObject;

Upvotes: 1

Related Questions