Search code examples
playnjbox2d

How to properly apply torque or angular impulse to body in PlayN?


I've been trying to apply an angular impulse to a Body object in PlayN, but to no avail. Whichever value (radials) I enter, the angle of the body never changes. I have tried to set the torque as well with no results.

Example code that doesn't work:

BodyDef def = new BodyDef();
def.type = BodyType.DYNAMIC;
Body body = world.createBody(def);

float degToRad = (float) (180 / Math.PI);
float radials = (float) (50 / degToRad);

// None of the following options work.
body.applyAngularImpulse(radials);       // Immediate angular change.
body.applyTorque(radials);               // Angular change over time.

How can I get a valid body object to change its angle without manually setting its angular velocity (e.g. with setAngularVelocity)?

Thanks in advance!

I did notice that the torque and angular velocity are reset by calling the setWake method, which I never do manually, but it is invoked by the Island class:

public void setAwake(boolean flag) {
    ...
    m_angularVelocity = 0.0f;
    m_torque = 0.0f;
    ...
}

Note: Setting the angular velocity is not an option because I rely on the physics simulation. I've found an article for Box2D angle rotation, but it didn't change the outcome of the applyAngularImpulse method.


Solution

  • I've debugged some, and come to the conclusion the values that I've been using were way too low. When going through the applyAngularImpulse code I noticed a few things:

    public void applyAngularImpulse(float impulse) {
        if (m_type != BodyType.DYNAMIC) {
            return;
        }
    
        if (isAwake() == false) {
            setAwake(true);
        }
        m_angularVelocity += m_invI * impulse;
    }
    

    m_invI is a really low value, something like 2.44882598E-4 so it makes sense if I use a too low value, that there is just no visible effect. If calculate the impulse from the question's example multiplied by the m_invI field:

    m_invI                                 = 0.00044882598 = 2.449E-4
    impulse          = 50 / 180 / PI       = 0.08841941282 = 8.842E-2
    m_invI * impulse = 2.449E-4 * 8.842E-2 = 0.00002165237 = 2.165E-5 <--
    

    That means just an angular velocity increment of 0.00002165237 per update cycle... Which is way too low to be noticeable it seems.

    Also, while browsing the Box2D forums for similar situations, I found it there's a best practice to include the body's inertia into your angular impulse calculation. Like this:

    body.applyAngularImpulse(speedValue * body.getInertia());
    

    The inertia tends to be a high value (+4000) for me.

    Hope this can be some help to others that have trouble applying an angular impulse or torque.