Can't get rotation from applyForce's rel_pos

Post Reply
zb10948
Posts: 3
Joined: Fri Sep 10, 2021 4:18 pm

Can't get rotation from applyForce's rel_pos

Post by zb10948 »

Hello,

I'm unable to achieve 'natural' rotation of a rigidbody by modifiying the position from centre of mass to offseted.

Code: Select all

		    btVector3 force(-1, 0, 0);
                    force *= 13.0f;

                    btVector3 thrust_position(0, 1.7, 0);
                    btVector3 com = body->getCenterOfMassPosition();
                    thrust_position += com;

                    body->applyForce(force, thrust_position);
Effect of this code is the same as running applyCentralForce(force). The getRotation() quaternion remains at (1, 0, 0, 0);

The body is rigidbody dynamic with a mass of 1 in world with no gravity, compound shape made of a few convex hulls. It rotates normally via manual transformation.

Am I doing this wrong and should I supply a world coordinate that matches some point on the hull itself? My goal is similar to aircraft thrust vectoring, by offsetting the thrust point from the centre.

Thanks for tips in advance :)
User avatar
drleviathan
Posts: 849
Joined: Tue Sep 30, 2014 6:03 pm
Location: San Francisco

Re: Can't get rotation from applyForce's rel_pos

Post by drleviathan »

I would expect the object to rotate after your applyForce() call. However, applyForce() only lasts for one substep so if you don't call it multiple times over several substeps it is possible your body won't pick up enough angular velocity to notice. The delta angular velocity from a single applyForce() with offset not only depends on the offset and strength of force, but also on the length of the substep and the angular inertia tensor of the object. Short substeps and large angular inertia tensor coefficients make for very sluggish objects after one poke with applyForce().

If you're trying to make a fun game, and don't want to tear your hair out tuning forces and offsets, then I would recommend NOT using applyForce() if you can help it and instead compute the angular velocity you want and slew the body's angular velocity toward your desired value. Something like this (in pseudocode):

Code: Select all

old_angular_velocity = body->getAngularVelocity();
delta = substep_duration / SLEW_PERIOD;
delta_angular_velocity = delta * (new_target_angular_velocity - old_angular_velocity);
if (delta_angular_velocity.length() > MIN_DELTA_ANGULAR_VELOCITY) {
    new_angular_velocity =  old_angular_velocity + delta_angular_velocity;
    body->setAngularVelocity(new_angular_velocity);
}
You then have a single value to tune: SLEW_PERIOD. It should be about 1/3 the time you would like it to take for your object to transition from current value to new value. So, if you want your object to transition in about 1 second you would set SLEW_PERIOD to be about 0.333. The reason for the MIN_DELTA_ANGULAR_VELOCITY is to prevent the logic above from keeping the body active when it doesn't need to be adjusted.
Post Reply